Подтвердить что ты не робот

Использование собственных объектов модуля в __main__.py

Я пытаюсь получить доступ к данным модулей изнутри __main__.py.

Структура выглядит следующим образом:

mymod/
    __init__.py
    __main__.py

Теперь, если я выставляю переменную в __init__.py следующим образом:

__all__ = ['foo']
foo = {'bar': 'baz'}

Как я могу получить доступ к foo из __main__.py?

4b9b3361

Ответ 1

Вам нужно либо иметь пакет уже в sys.path, добавить каталог с mymod в sys.path в __main__.py, либо использовать переключатель -m.

Чтобы добавить mymod к пути, будет выглядеть примерно так (в __main__.py):

import sys
import os
path = os.path.dirname(sys.modules[__name__].__file__)
path = os.path.join(path, '..')
sys.path.insert(0, path)
from myprog import function_you_referenced_from_init_file

Использование переключателя -m:

python -m mymod

Подробнее см. этот ответ.

Ответ 2

Проблема, с которой я сталкиваюсь больше всего в этом, заключается в том, что я часто хочу запустить файл __init__.py как script для тестирования функций, но их не следует запускать при загрузке пакета. Существует полезное временное решение для разных путей выполнения между python <package>/__init__.py и python -m <package>.

  • $ python -m <module> выполняет <package>/__main__.py. __init__.py не загружен.
  • $ python <package>/__init__.py просто выполняет script __init__.py как обычный script.


Проблема

Если мы хотим __init__.py иметь предложение if __name__ == '__main__': ..., которое использует материал из __main__.py. Мы не можем импортировать __main__.py, потому что он всегда будет импортировать __main__.pyc из пути интерпретаторов. (Если... мы прибегаем к абсолютным путям импорта, которые могут вызвать много других беспорядков).


Решение Решение:)

Используйте два файла script для модулей __main__:

<package>/
         __init__.py
         __main__.py
         main.py

# __init__.py

# ...
# some code, including module methods and __all__ definitions

__all__ = ['foo', 'bar']
bar = {'key': 'value'}
def foo():
    return bar
# ...
if __name__ == '__main__':
    from main import main
    main.main()

# __main__.py

# some code...such as:
import sys
if (len(sys.argv) > 1 and sys.argv[1].lower() == 'option1'):
    from main import main()
    main('option1')
elif (len(sys.argv) > 1 and sys.argv[1].lower() == 'option2'):
    from main import main()
    main('option2')
else:
    # do something else?
    print 'invalid option. please use "python -m <package> option1|option2"'

# main.py

def main(opt = None):
    if opt == 'option1':
        from __init__ import foo
        print foo()
    elif opt == 'option2':
        from __init__ import bar
        print bar.keys()
    elif opt is None:
        print 'called from __init__'

Импорт в main.py, вероятно, не идеален в случае, если мы запускаем от __init__.py, поскольку мы перезагружаем их в локальную область другого модуля, несмотря на то, что они уже загружают их в __init__.py, но явные загрузка должна избегать круговой нагрузки. Если вы снова загрузите весь модуль __init__ в main.py, он не будет загружен как __main__, поэтому он должен быть безопасным для круговой загрузки.

Ответ 3

Модуль __init__ пакет действует как члены самого пакета, поэтому объекты импортируются непосредственно из mymod:

from mymod import foo

или

from . import foo

если вам нравится быть кратким, читайте относительный импорт. Вам, как всегда, необходимо убедиться, что вы не вызываете модуль как mymod/__main__.py, так как это предотвратит обнаружение Python mymod в качестве пакета. Возможно, вы захотите изучить distutils.

Ответ 4

Если вы запустите модуль с python -m mymod, тогда код в __main__.py сможет импортировать из остальной части модуля, не добавляя модуль в sys.path.

Ответ 5

Структура каталога модуля выглядит следующим образом:

py/
   __init__.py
   __main__.py

__ __ INIT. Ру

#!/usr/bin/python3
#
# __init__.py
#

__all__ = ['foo']
foo = {'bar': 'baz'}
info = { "package": __package__,
         "name": __name__,
         "locals": [x for x in locals().copy()] }
print(info)

__ __ главное. Р

#!/usr/bin/python3
#
# __main__.py
#

info = { "package": __package__,
         "name": __name__,
         "locals": [x for x in locals().copy()] }
print(info)
from . import info as pyinfo
print({"pyinfo: ": pyinfo})

Выполнить модуль как script с помощью флага -m

$ python -m py

# the printout from the 'print(info)' command in __init__.py
{'name': 'py', 'locals': ['__all__', '__builtins__', '__file__', '__package__', '__path__', '__name__', 'foo', '__doc__'], 'package': None}
# the printout from the 'print(info)' command in __main__.py
{'name': '__main__', 'locals': ['__builtins__', '__name__', '__file__', '__loader__', '__doc__', '__package__'], 'package': 'py'}
# the printout from the 'print(pyinfo)' command in __main__.py
{'pyinfo: ': {'name': 'py', 'locals': ['__all__', '__builtins__', '__file__', '__package__', '__path__', '__name__', 'foo', '__doc__'], 'package': None}}