Использование собственных объектов модуля в __main__.py
Я пытаюсь получить доступ к данным модулей изнутри __main__.py
.
Структура выглядит следующим образом:
mymod/
__init__.py
__main__.py
Теперь, если я выставляю переменную в __init__.py
следующим образом:
__all__ = ['foo']
foo = {'bar': 'baz'}
Как я могу получить доступ к foo
из __main__.py
?
Ответы
Ответ 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}}