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包它是字典之后,但它是可能的将它从字典中删除。这是我仅为了教学目的而提出的一点,我不会在真实应用中推荐这种方法。此外,如果您需要将您的miscutil包装在一起,这不会很好。如果可能的话重新安排你的源代码结构以更好地适应普通的Python模块加载机制。

这是由Python 3.3中的隐式命名空间包解决的。见PEP-420

+0

这似乎是python 3的正确答案,虽然有一个工作示例的解释会很有用。 – funseiki 2018-02-16 18:37:14

这是改编的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