我正在尝试从__main__.py
内部访问模块的数据。
结构如下:
mymod/
__init__.py
__main__.py
现在,如果我在__init__.py
中公开变量,就像这样:
__all__ = ['foo']
foo = {'bar': 'baz'}
如何从foo
访问__main__.py
?
答案 0 :(得分:23)
您需要将软件包放在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
有关详细讨论,请参阅this answer。
答案 1 :(得分:4)
我遇到这种类型的问题最常见的问题是我经常要将__init__.py
文件作为脚本运行来测试功能,但在加载包时不应运行这些。 python <package>/__init__.py
和python -m <package>
之间的不同执行路径有一个有用的解决方法。
$ python -m <module>
执行<package>/__main__.py
。 __init__.py
未加载。$ python <package>/__init__.py
只是像普通脚本一样执行脚本__init__.py
。
当我们希望__init__.py
有if __name__ == '__main__': ...
条款使用来自__main__.py
的内容时。我们无法导入__main__.py
,因为它始终会从解释器的路径导入__main__.pyc
。 (除非 ...我们采用绝对路径导入黑客,这可能会导致很多其他混乱)。
为模块的__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
中的导入可能并不理想,因为我们正在将它们重新加载到另一个模块的本地范围内,尽管已在{{1}中加载它们已经,但显式加载应避免循环加载。如果您在__init__.py
中再次加载整个__init__
模块,则不会将其加载为main.py
,因此就圆形加载而言应该是安全的。
答案 2 :(得分:2)
a package的__init__
模块就像包本身的成员一样,因此对象直接从mymod
导入:
from mymod import foo
或者
from . import foo
如果您想要简洁,请阅读relative imports。您需要一如既往地确保不要将模块调用为mymod/__main__.py
,因为这会阻止Python将mymod
检测为包。您可以查看distutils
。
答案 3 :(得分:1)
如果您使用python -m mymod
运行模块,则__main__.py
中的代码将能够从模块的其余部分导入,而无需将模块添加到sys.path
。
答案 4 :(得分:0)
我发现第一个答案很有用(即,hacking sys.path
),但是在 Python 3.4 中添加了 pathlib
后,我发现以下代码更加简单和 Pythonic:< /p>
import sys
from pathlib import Path
# You don't need to .insert(), just append
sys.path.append(str(Path(__file__).parent.parent))