Python从分发在不同目录中的包访问模块

时间:2010-05-17 06:55:48

标签: python module packages

我对一个分布在多个目录中的单个模块有疑问。

假设我有这两个文件和目录:

~/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。

如何解决此问题?

4 个答案:

答案 0 :(得分:2)

你不能没有极端的诡计将一个包结构拉到另一个包结构中。 Python要求包中的所有模块都在一个子目录下。请参阅os来源,了解其处理方式os.path

答案 1 :(得分:1)

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模块加载机制。

答案 2 :(得分:1)

Python 3.3中的隐式命名空间包解决了这个问题。请参阅PEP-420

答案 3 :(得分:1)

这是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

要添加到Python路径的一些setup.sh文件:

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