在__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}}