Python从分布在不同目录的包中访问模块
我有一个关于分布在多个目录中的单个模块的问题。Python从分布在不同目录的包中访问模块
比方说,我有这两个文件和目录:
~/lib/python
xxx
__init__.py
util
__init__.py
module1.py
module2.py
~/graphics/python
xxx
__init__.py
misc
__init__.py
module3.py
module4.py
所以后来在我的Python模块,我这样做:
import sys
pythonlibpath = '~/lib/python'
if pythonlibpath not in sys.path: sys.path.append(pythonlibpath)
import xxx.util.module1
其中工程。现在
,问题是,我需要xxx.misc.module3,所以我这样做:
import sys
graphicslibpath = '~/graphics/python'
if graphicslibpath not in sys.path: sys.path.append(graphicslibpath)
import xxx.misc.module3
,但我得到这个错误:
ImportError: No module named misc.module3
好像它在某种程度上还记得在〜/ lib/python中有一个xxx包,然后尝试从那里找到misc.module3。
我该如何解决这个问题?
你不能没有极端的欺骗,将一个包装结构拉入另一个。 Python要求包中的所有模块都在一个子目录下。请参阅os
来源了解它如何处理os.path
。
Python确实记得有一个xxx
包。为了达到可接受的性能,这是非常必要的,一旦模块和包被加载,它们被缓存。您可以通过查看字典sys.modules
来查看哪些模块已加载。
sys.modules
是一个正常的字典,以便您可以删除一个包从它,迫使它重新加载象下面这样:
import sys
print sys.modules
import xml
print sys.modules
del sys.modules['xml']
print sys.modules
注意导入xml
包它是字典之后,但它是可能的将它从字典中删除。这是我仅为了教学目的而提出的一点,我不会在真实应用中推荐这种方法。此外,如果您需要将您的misc
和util
包装在一起,这不会很好。如果可能的话重新安排你的源代码结构以更好地适应普通的Python模块加载机制。
这是改编的answer to a similar question。
继续@ Gary的回答,PEP 420 page表示在共享的__init__.py
包中使用以下代码。
__init__.py
:
from pkgutil import extend_path
__path__ = extend_path(__path__, __name__)
此代码应被置于其内的XXX目录的__init__.py
。 见* S下方
someroot/
├── graphics
│ └── python
│ └── xxx
│ ├── ****__init__.py****
│ └── misc
│ ├── __init__.py
│ ├── module3.py
│ └── module4.py
└── lib
└── python
└── xxx
├── ****__init__.py****
└── util
├── __init__.py
├── module1.py
└── module2.py
一些setup.sh
文件添加到Python的路径:
libPath=someroot/lib/python/
graphicsPath=someroot/graphics/python/
export PYTHONPATH=$PYTHONPATH:$libPath:$graphicsPath
的Python测试代码(使用pyenv Python版本2.7.14和3.6.4测试):
import xxx.util.module1
import xxx.misc.module3 # No errors
这似乎是python 3的正确答案,虽然有一个工作示例的解释会很有用。 – funseiki 2018-02-16 18:37:14