具有公共包层次结构的模块可以在我的 PYTHONPATH 中多次提及吗?
我有两个共享包名称的独立项目。只要它们不在 PYTHONPATH 上,它们就可以正常运行,但是一旦它们都出现,其中一个就无法在自己的项目中找到导入。
例如,像这样的两个项目:
项目 1:
x/
__init__.py
test.py
foo.py
test.py 包含行:
import x.foo
项目 2:
x/
__init__.py
bar.py
如果我运行,
PYTHONPATH=. python x/y/test.py
则没有错误。但是如果我运行
PYTHONPATH='pathtoproject2:.' python x/test.py
我会收到错误:
Traceback (most recent call last):
File "x/test.py", line 1, in <module>
import x.foo
ImportError: No module named foo
有没有办法让具有公共包的不同 Python 项目共享 PYTHONPATH?或者Python将始终只使用找到包的第一个路径?
注意:我知道如果您将 import from x.foo 修改为 import foo 那么它就会起作用。但我想知道是否可以在不修改任何一个包的情况下做到这一点。
I have two separate projects that share a package name. They run OK as long as they are not both on the PYTHONPATH, but as soon as they both appear one of them cannot find imports in its own project.
Example, two projects like this:
Project 1:
x/
__init__.py
test.py
foo.py
test.py contains the line:
import x.foo
Project 2:
x/
__init__.py
bar.py
If I run
PYTHONPATH=. python x/y/test.py
there is no error. But if I run
PYTHONPATH='pathtoproject2:.' python x/test.py
I get the error:
Traceback (most recent call last):
File "x/test.py", line 1, in <module>
import x.foo
ImportError: No module named foo
Is there a way to have different Python projects with a common package share the PYTHONPATH? Or will Python always use only the first path where a package is found?
Note: I know if you modify the import from x.foo to import foo then it will work. But I want to know if it is possible to do it without modifying either package.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
尽管导入机制本身不支持,但有一个解决方案可以在 python 中创建命名空间包。您只需将以下代码放在两个 __init__.py 文件中即可。
pkg_resources 由 setuptools python 包提供,其优点是还可以处理 Egg zip 文件中包含的包。
pkgutil 包含在 python 的标准库中,因此如果系统中未安装 setuptools,我们将依赖它来处理命名空间扩展。
有关 python 命名空间包的更多信息,请访问:
http://packages.python .org/distribute/setuptools.html#namespace-packages
http://www.python.org/dev/peps/pep-0382/
Although not supported natively by the import mechanism, there is a workaround solution to create namespaced packages in python. You just have to put the following code on both __init__.py files.
pkg_resources is provided by setuptools python package and has the advantage that also handles packages contained within egg zip files.
pkgutil is contained in python's standard library so we rely on it to handle the namespace extension if setuptools is not installed in the system.
for more information about python namespace packages can be found here:
http://packages.python.org/distribute/setuptools.html#namespace-packages
http://www.python.org/dev/peps/pep-0382/
目前,Python 不支持来自不同目录的包。包是一个单元,而不仅仅是一个命名空间。这与 Java“包”或更恰当地称为 .NET 中的“命名空间”不同。
导入包时,Python 将按顺序扫描 sys.path,并使用第一个匹配项。如果路径后面出现的目录中有另一个具有匹配名称的模块或包,则不会找到它。
顺便说一句,你的“笔记”不是真的。当您使用
import foo
时,Python 将在test.py
目录中尝试相对导入,找不到匹配项,然后尝试绝对导入模块foo< /code>,它也不存在,然后引发
ImportError
。不要使用包名称来使用公共前缀对模块进行分组,而是将包视为小型的独立库。在Python中,扁平比嵌套更好,拥有多个顶级包(每个包实现一个不同的目的)比拥有一个大型单片包更好。只需使用
foo
和bar
,而不是org.example.foo
和org.example.bar
。Currently, Python does not support packages from different directories. A package is an unit, not just a namespace. This is different from Java "packages" or the more appropriately named "namespaces" in .NET.
When importing a package, Python will scan
sys.path
, sequentially, and use the first match. If there is another module or package with a matching name in a directory that appears later in the path, it won't be found.Your "note" is not true, by the way. When you use
import foo
, Python will try a relative import within the directory oftest.py
, find no match, then attempt an absolute import of modulefoo
, which does not exist either, and then raise anImportError
.Instead of using package names to group modules using a common prefix, think of packages as smallish, self-contained libraries. In Python, flat is better than nested, and it is preferable to have multiple top-level packages, each fulfilling one distinct purpose, than having one large monolithic package. Instead of
org.example.foo
andorg.example.bar
, just usefoo
andbar
.