[英]Python accessing modules from package that is distributed over different directories
I have a question regarding one single module that is distributed over multiple directories. 我有一个关于分布在多个目录上的单个模块的问题。
Let's say I have these two file and directories: 假设我有这两个文件和目录:
~/lib/python
xxx
__init__.py
util
__init__.py
module1.py
module2.py
~/graphics/python
xxx
__init__.py
misc
__init__.py
module3.py
module4.py
So then in my Python modules, I did this: 那么在我的Python模块中,我这样做了:
import sys
pythonlibpath = '~/lib/python'
if pythonlibpath not in sys.path: sys.path.append(pythonlibpath)
import xxx.util.module1
which works. 哪个有效。
Now, the problem is that I need xxx.misc.module3, so I did this: 现在,问题是我需要xxx.misc.module3,所以我这样做了:
import sys
graphicslibpath = '~/graphics/python'
if graphicslibpath not in sys.path: sys.path.append(graphicslibpath)
import xxx.misc.module3
but I get this error: 但我得到这个错误:
ImportError: No module named misc.module3
It seems like it somehow still remembers that there was a xxx package in ~/lib/python and then tries to find misc.module3 from there. 似乎它仍然记得在〜/ lib / python中有一个xxx包然后尝试从那里找到misc.module3。
How do I get around this issue? 我该如何解决这个问题?
You can't without an extreme amount of trickery that pulls one package structure into the other. 你不能没有极端的诡计将一个包结构拉到另一个包结构中。 Python requires that all modules in a package be under a single subdirectory.
Python要求包中的所有模块都在一个子目录下。 See the
os
source to learn how it handles os.path
. 请参阅
os
源以了解它如何处理os.path
。
Python does indeed remember that there was a xxx
package. Python确实记得有一个
xxx
包。 This is pretty much necessary to achieve acceptable performance, once modules and packages are loaded they are cached. 这对于实现可接受的性能非常必要,一旦加载了模块和包,它们就会被缓存。 You can see which modules are loaded by looking the the dictionary
sys.modules
. 您可以通过查看字典
sys.modules
来查看加载了哪些模块。
sys.modules
is a normal dictionary so you can remove a package from it to force it to be reloaded like below: sys.modules
是一个普通的字典,所以你可以从中删除一个包来强制它重新加载,如下所示:
import sys
print sys.modules
import xml
print sys.modules
del sys.modules['xml']
print sys.modules
Notice that after importing the xml
package it is the dictionary, however it is possible to remove it from that dictionary too. 请注意,在导入
xml
包之后它是字典,但是也可以从该字典中删除它。 This is a point I make for pedagogical purposes only, I would not recommend this approach in a real application . 这是我仅用于教学目的的一点, 我不建议在实际应用中使用这种方法 。 Also if you need to use your
misc
and util
packages together this would not work so great. 此外,如果您需要将
misc
和util
软件包一起使用,这将无法实现。 If at all possible rearrange your source code structure to better fit the normal Python module loading mechanism. 如果可能的话,重新安排你的源代码结构,以更好地适应普通的Python模块加载机制。
This is an adaptation of an answer to a similar question . 这是对类似问题的回答的改编。
Following up on @Gary's answer, the PEP 420 page says to use the following code on shared __init__.py
packages. 按照@ Gary的回答, PEP 420页面说在共享的
__init__.py
包上使用以下代码。
__init__.py
: __init__.py
:
from pkgutil import extend_path
__path__ = extend_path(__path__, __name__)
This code should be placed inside the xxx directory's __init__.py
. 此代码应放在xxx目录的
__init__.py
。 See the *s below 见下面的* 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
Some setup.sh
file to add to the Python Path: 一些要添加到Python路径的
setup.sh
文件:
libPath=someroot/lib/python/
graphicsPath=someroot/graphics/python/
export PYTHONPATH=$PYTHONPATH:$libPath:$graphicsPath
Python test code (tested on Python versions 2.7.14 and 3.6.4 using pyenv ): Python测试代码(使用pyenv在Python版本2.7.14和3.6.4上测试 ):
import xxx.util.module1
import xxx.misc.module3 # No errors
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.