Python: как получить доступ к переменной, объявленной в родительском модуле

Использование структуры из документов Python:

sound/
  __init__.py
  effects/
          __init__.py
          echo.py
          surround.py
          reverse.py

Скажем, я хочу import sound.effects и получить список доступных эффектов. Я мог бы сделать это, объявив переменную уровня модуля в sound.effects, а затем добавив к ней, когда будет импортирован каждый .py файл. Таким образом, звук/эффекты/__ init__.py может выглядеть так:

effectList = []
import echo
import surround   # Could write code to import *.py instead
...

Из моего основного кода я могу теперь получить доступ к sound.effects.effectList, чтобы получить список эффектов, но как мне получить доступ к effectList изнутри echo.py, чтобы сделать фактическое добавление? Я застреваю, пытаясь получить доступ к переменной:

# None of these work :-(
# from . import self
# from .. import effects
# import sound.effects

sound.effect.effectList.append({'name': 'echo'})

Ответ 1

То, что обычно делают люди в этой ситуации, это создать файл common.py в модуле.

sound/
  __init__.py
  effect/
          __init__.py
          common.py
          echo.py
          surround.py
          reverse.py

Затем вы переместите код с __init__.py на common.py:

effectList = []
import echo
import surround   # Could write code to import *.py instead
...

Внутри __init__.py у вас есть следующее:

from common import *

Итак, теперь в echo.py у вас будет следующее:

import common
common.effectList.append({'name': 'echo'})

Любой импортирующий звук будет использовать его так:

import sound.effect

for effect_name,effect in sound.effect.effectlist.items():
    #....

Я только начал использовать это самостоятельно, но я считаю, что это обычная практика в сообществе python.

Ответ 2

Я думаю, что вы должны оставить "сделать доступным" в __init__.py внутри пакета effects, а не все модули автоматически заполнять effectList. Несколько причин, о которых я могу думать.

  • Вы не можете импортировать какие-либо эффекты, кроме как через пакет, если вам удалось каким-то образом получить эту работу (кроме модуля effectList в модуле импорта).
  • Вам нужно вручную добавить приложение в каждом произнесенном вами эффекте. Было бы лучше, если бы вы только что внедрили import *.py как вещь в __init__.py, которая загружала все в текущую директорию и делала ее доступной.

Что-то вроде этого в вашем __init__.py.

import os, glob

effectslist = []

for i in glob.glob("*.py"):
    if i == "__init__.py":
        next
    print "Attempting to import %s"%i
    try:
        mod = __import__(os.path.splitext(i)[0])
        effectslist.append(mod)
    except ImportError,m:
        print "Error while importing %s - %s"%(i,m)