这是我的目录结构
.
|-- path1
| `-- mynms
| |-- __init__.py
| `-- app1
| |-- __init__.py
| `-- foo.py
|-- path2
| `-- mynms
| |-- __init__.py
| `-- app2
| |-- __init__.py
| `-- bar.py
`-- user.py
文件内容:
$ cat user.py
#!/usr/bin/python
import sys
sys.path.append('path1')
sys.path.append('path2')
from mynms.app2.foo import foo
from mynms.app2.bar import bar
foo()
bar()
$ cat path1/mynms/__init__.py;echo ==============;cat path2/mynms/__init__.py
from pkgutil import extend_path
__path__ = extend_path(__path__, __name__)
print "I am path1/mynms/__init__.py"
==============
from pkgutil import extend_path
__path__ = extend_path(__path__, __name__)
print "I am path2/mynms/__init__.py"
$ cat path1/mynms/app1/foo.py; echo ============; cat path2/mynms/app2/bar.py
def foo():
print "foo!"
============
def bar():
print "bar!"
问题:当我运行user.py时,我只获取path1 / __ init__.py的输出,但不获取path2的输出。有没有办法解决这个问题?
$ ./user.py
I am path1/mynms/__init__.py -----> Why is 'I am path2/mynms/__init__.py not printed?
foo!
bar!
答案 0 :(得分:3)
当您编写import mynms.app2.foo
或from mynms.app2.foo import foo
时,Python会执行此操作:
mynms
mynms/__init__.py
来导入path1
通过查找文件mynms.app1
(或mynms/app1/__init__.py
) mynms/app1.py
mynms.app1.foo
(或mynms/app1/foo.py
)mynms/app1/foo/__init__.py
在下一个导入语句import mynms.app2.bar
上,Python执行:
mynms
- 它已经导入,所以没有任何关系。 (您可以查看sys.modules['mynms']
以查看它是否已导入。如果不是,则会引发KeyError
。)mynms.app2
- 再次,这已经导入。mynms.app2.bar
mynms/app2/bar.py
文件导入path2
Python没有(明智的)方法从两个不同的文件中导入mynms
模块两次。
如果您有初始化代码,则需要将它们放在模块mynms.app1
和mynms.app2
中,以便它们具有不同的名称。即文件mynms/app1/__init__.py
和mynms/app2/__init__.py
。
答案 1 :(得分:1)
正如Martijn Pieters在评论中已经提到的,Python 2不支持作为包集合分发的包。但是如果使用setuptools
(很可能是你),你可以模仿这样的包。
唯一的问题是包应该具有正确的元信息,因此setuptools
可以在虚拟单个包中连接多个子包。这些信息通常会传递到setup()
中的setup.py
函数,并在安装后存在于site-packages
目录中。这意味着那些分发包装的人应该做出适当准备的东西,你很难将它们放在PATH
中以使它们起作用。
Here是相应文档的链接。准备花一些时间,因为PEAK文档并不总是足以快速启动。
答案 2 :(得分:0)
我同意其余的评论 - 这是错误的代码结构,应该尽快重构。但是,如果你真的,真的,真的不能或者 ,那么你可以通过使用标准库中的imp模块来破坏导入内部:
https://docs.python.org/2/library/imp.html
例如,您可以通过执行以下操作导入不在普通python模块搜索路径中的文件:
/Users/me/test.py:
def run_foo():
print "hi got here"
和另一个脚本:
import imp
foo = imp.load_source("foo", "/Users/me/test.py")
foo.run_foo()
同样,你正在反对Python这样做,而不是用它。但这是一个很好的技巧。