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