在__main__.py中使用模块自己的对象
我试图从__main__.py
访问模块的数据。
结构如下:
mymod/ __init__.py __main__.py
现在,如果我像这样在__init__.py
显示一个variables:
__all__ = ['foo'] foo = {'bar': 'baz'}
我如何从__main__.py
访问foo
?
您需要在sys.path
包含该包,将包含mymod
的目录添加到__main__.py
sys.path
中,或者使用-m
开关。
将mymod
添加到path中看起来像这样(在__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
看到这个答案更多的讨论。
我遇到的这种问题最常见的问题是,我经常想将__init__.py
文件作为脚本来运行,以便testing特性,但是在加载包时不应该运行这些文件。 对于python <package>/__init__.py
和python -m <package>
之间的不同执行path有一个有用的解决方法。
-
$ python -m <module>
执行<package>/__main__.py
。__init__.py
未加载。 -
$ python <package>/__init__.py
只是像普通脚本一样执行脚本__init__.py
。
问题
当我们想要__init__.py
有一个if __name__ == '__main__': ...
__init__.py
if __name__ == '__main__': ...
子句使用来自__main__.py
东西。 我们不能导入__main__.py
因为它总是会从解释器的path中导入__main__.pyc
。 ( 除非 …我们诉诸绝对path导入黑客,这可能会导致很多其他的混乱)。
解决scheme 一个办法 :)
为模块的__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__'
在我们从__init__.py
运行的情况下, main.py
中的导入可能并不理想,因为我们将它们重新加载到另一个模块的本地范围中,尽pipe已经将它们加载到__init__.py
,但是显式加载应该避免循环加载。 如果你在main.py
再次加载整个__init__
模块,它将不会被加载为__main__
,所以就循环加载而言应该是安全的。
包的__init__
模块就像包本身的成员一样,所以这些对象直接从mymod
中导入:
from mymod import foo
要么
from . import foo
如果你喜欢简洁,那么阅读相关的import 。 您需要像往常一样确保您不会像mymod/__main__.py
那样调用模块,因为这会阻止Python将mymod
作为一个包进行检测。 你可能希望看到distutils
。
如果使用python -m mymod
运行模块,则__main__.py
代码将能够从模块的其余部分导入,而不必将模块添加到sys.path
。
模块目录结构如下:
py/ __init__.py __main__.py
__init__.py
#!/usr/bin/python3 # # __init__.py # __all__ = ['foo'] foo = {'bar': 'baz'} info = { "package": __package__, "name": __name__, "locals": [x for x in locals().copy()] } print(info)
__main__.py
#!/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})
使用-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}}