【问题标题】:Python: modules and packaging - why isn't __init__.py file executed before __main__.py?Python:模块和打包 - 为什么 __init__.py 文件不在 __main__.py 之前执行?
【发布时间】:2013-09-03 09:26:04
【问题描述】:

我有一个完全包含在具有以下结构的目录中的 python 程序:

myprog/
├── __init__.py
├── __main__.py
├── moduleone.py
└── moduletwo.py

我希望能够打包并分发它,以便其他开发人员可以执行pip install -e /path/to/git/clone/of/myprog,然后可以在他自己的程序中导入 myprog 并用它做一些很酷的事情。

我还希望能够在命令行中运行 myprog,如下所示:

PROMPT> python myprog

当我这样做时,我希望 python 执行 __main__.py 模块,它确实如此。但是,该模块引用了在__init__.py 中声明的一些函数,这些函数在程序在命令行运行和被另一个程序导入时都需要可用。但是,我收到以下错误:

NameError: name 'function_you_referenced_from_init_file' is not defined

我是否必须以某种方式将这些函数导入__main__.py

我尝试了一个简单的例子如下:

PROMPT> cat myprog/__init__.py
def init_myprog():
    print 'running __init__.init_myprog()'

PROMPT> cat myprog/__main__.py
import myprog
print 'hi from __main__.py'
myprog.init_myprog()

PROMPT> ls -l myprog
total 16
-rw-r--r--  1 iit    63B Aug 30 11:40 __init__.py
-rw-r--r--  1 iit    64B Aug 30 12:11 __main__.py

PROMPT> python myprog
Traceback (most recent call last):
  File "/usr/local/Cellar/python/2.7.5/Frameworks/Python.framework/Versions/2.7/lib/python2.7/runpy.py", line 162, in _run_module_as_main
    "__main__", fname, loader, pkg_name)
  File "/usr/local/Cellar/python/2.7.5/Frameworks/Python.framework/Versions/2.7/lib/python2.7/runpy.py", line 72, in _run_code
    exec code in run_globals
  File "/Users/jon/dev/myprog/__main__.py", line 1, in <module>
    import myprog
ImportError: No module named myprog

【问题讨论】:

  • 致投票结束这个问题的人——如果它是如此愚蠢和简单,也许你可以在几秒钟内向我解释一下?我试图从这个链接中学习stackoverflow.com/questions/3411293/…,但仍然遇到问题。
  • 您必须导入除内​​置函数之外的所有内容,因此答案是非常明显的“是”。

标签: python module python-module


【解决方案1】:

所以,在看了其他回复后并没有感到兴奋,我尝试了:

from __init__ import *

来自我的__main__.py 文件。

我想它不允许您按名称引用模块,但对于简单的情况,它似乎可以工作。

【讨论】:

    【解决方案2】:

    我是否必须以某种方式将这些函数导入__main__

    是的。只有 builtins 中的项目在没有导入的情况下可用。比如:

    from myprog import func1, func2
    

    应该可以解决问题。

    如果您没有在正常的 python 路径中安装myprog,那么您可以通过以下方式解决它:

    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
    

    坦率地说,这很可怕。

    我建议使用MartijnPieters suggestion 并将-m 放在命令行上,在这种情况下__main__.py 可能看起来像:

    from myprog import function_you_referenced_from_init_file
    

    【讨论】:

    • 这看起来不错,但它在我的机器上不起作用。我尝试了两种或三种不同的导入变体,但总是得到“ImportError: No module named myprog”
    • @JonCrowell:那么你没有安装 myprog 模块,所以 Python 没有找到它。看打包开发:guide.python-distribute.orgscotttorborg.com/python-packaging快速hack:将myprog上面的目录添加到PYTHOPATH中。
    【解决方案3】:

    __init__.py 仅在您导入 时加载。相反,您通过执行目录将目录视为脚本

    您仍然可以将包视为脚本,而不是目录。通过使用-m 开关,将目录视为包作为主脚本:

    python -m myprog
    

    【讨论】:

    • 我试过了,现在得到一个No module named myprogThis answer 似乎表明将目录视为包脚本是不好的做法。想法?
    • 答案陈述个人意见。几个标准库模块,以及virtualenvpip 等流行的包都支持作为脚本运行。我个人很欣赏并使用这个功能。如果您遇到 No module named Foo 错误,则您的模块也无法导入;你确定它在你的 Python 路径上可用吗?
    猜你喜欢
    • 2015-09-28
    • 2017-12-12
    • 2012-10-16
    • 2021-07-10
    • 2019-09-27
    • 1970-01-01
    • 2013-04-21
    • 1970-01-01
    • 2018-01-13
    相关资源
    最近更新 更多