Python:模块和打包 - 为什么在__main__.py之前没有执行__init__.py文件?

时间:2013-08-30 15:24:36

标签: python module python-module

我有一个完全包含在具有以下结构的目录中的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

3 个答案:

答案 0 :(得分:14)

只有在导入时才会加载__init__.py。您可以通过执行目录将目录视为脚本

您仍然可以将程序包视为脚本,而不是目录。要将目录作为包作为主脚本处理,请使用-m开关:

python -m myprog

答案 1 :(得分:9)

  

我是否必须以某种方式将这些功能导入__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

答案 2 :(得分:3)

所以,看了其他的回答而不是激动,我试过了:

from __init__ import *

来自我的__main__.py文件。

我想它不允许你按名称引用模块,但对于简单的情况,它似乎有效。