45

我正在尝试从其内部访问模块的数据__main__.py

结构如下:

mymod/
    __init__.py
    __main__.py

现在,如果我像这样公开一个变量__init__.py

__all__ = ['foo']
foo = {'bar': 'baz'}

我如何foo访问__main__.py

4

6 回答 6

23

您需要将包已经在 中sys.path,将包含的目录添加mymodsys.pathin 中__main__.py,或者使用-m开关。

添加mymod到路径看起来像这样(in __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

有关更多讨论,请参阅此答案

于 2010-08-05T11:11:18.417 回答
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,因为我们正在将它们重新加载到另一个模块的本地范围中,尽管已经加载了它们__init__.py,但是显式加载应该避免循环加载。如果您确实在 中再次加载整个__init__模块main.py,它将不会被加载为__main__,因此就循环加载而言应该是安全的。

于 2012-07-19T18:41:26.863 回答
2

__init__模块就像包本身的成员一样,因此对象直接从以下位置导入:mymod

from mymod import foo

或者

from . import foo

如果您喜欢简洁,请阅读有关相对导入的内容。您需要像往常一样确保不要将模块调用为mymod/__main__.py,例如,因为这会阻止 Python 检测mymod为包。您不妨研究一下distutils

于 2010-08-05T02:20:57.170 回答
1

如果您使用然后运行模块,python -m mymod则代码__main__.py将能够从模块的其余部分导入,而无需将模块添加到sys.path.

于 2012-05-10T19:57:17.970 回答
0

我发现第一个答案很有用(即 hacking sys.path),但是随着pathlibPython 3.4 中的添加,我发现以下代码更加简单和 Pythonic:

import sys
from pathlib import Path

# You don't need to .insert(), just append
sys.path.append(str(Path(__file__).parent.parent))
于 2021-07-29T22:57:33.293 回答
-2

模块目录结构如下:

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}}
于 2012-03-19T06:06:05.167 回答