gpt4 book ai didi

Python 3.6.0 隐式命名空间包

转载 作者:太空狗 更新时间:2023-10-30 00:16:24 26 4
gpt4 key购买 nike

我在 Python 3.6.0rc1 中发现了隐式命名空间包的奇怪行为。你能告诉我我错了吗还是 Python 3.6 错误?

我正在使用命名空间包 marrow,它有两个独立的包 marrow.utilmarrow.mailer。第二个依赖于第一个。

假设我们在 site-packages 中为 Python 2.7、3.5 和 3.6 安装了 marrow.util:

$ ls -la /usr/lib/python*/site-packages/marrow
/usr/lib/python2.7/site-packages/marrow:
total 24
drwxr-xr-x. 3 root root 4096 Dec 23 12:23 .
drwxr-xr-x. 196 root root 16384 Dec 23 12:23 ..
drwxr-xr-x. 3 root root 4096 Dec 23 12:23 util

/usr/lib/python3.5/site-packages/marrow:
total 12
drwxr-xr-x. 3 root root 4096 Dec 23 12:24 .
drwxr-xr-x. 99 root root 4096 Dec 23 12:24 ..
drwxr-xr-x. 4 root root 4096 Dec 23 12:24 util

/usr/lib/python3.6/site-packages/marrow:
total 12
drwxr-xr-x. 3 root root 4096 Dec 23 14:25 .
drwxr-xr-x. 37 root root 4096 Dec 23 14:25 ..
drwxr-xr-x. 4 root root 4096 Dec 23 14:25 util

这里没有__init__.py文件,这是正确的,因为marrow是一个命名空间包。您可以在安装期间看到此日志消息:

Skipping installation of <deleted>/site-packages/marrow/__init__.py (namespace package)

然后您在其他目录中构建(但未安装)marrow 命名空间包 marrow.mailer 的第二部分。例如像这样:

$ pwd
/builddir/build/BUILD/marrow.mailer-4.0.2

$ ls
coverage.xml debuglinks.list elfbins.list LICENSE.txt marrow.mailer.egg-info README.textile setup.py debugfiles.list debugsources.list example marrow PKG-INFO setup.cfg test

$ ls marrow/
__init__.py __init__.pyc mailer __pycache__

当我在此文件夹中运行 Python 2.7.12 或 3.5.2 并尝试导入 marrow.util(来自站点包)时,它按预期工作。

$ pwd
/builddir/build/BUILD/marrow.mailer-4.0.2

$ python2
Python 2.7.12 (default, Sep 29 2016, 12:52:02)
[GCC 6.2.1 20160916 (Red Hat 6.2.1-2)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import marrow.util
>>>

$ python3.5
Python 3.5.2 (default, Sep 14 2016, 11:28:32)
[GCC 6.2.1 20160901 (Red Hat 6.2.1-1)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import marrow.util
>>>

但是当我尝试使用 Python 3.6 导入相同的模块时,它失败了:

$ python3.6
Python 3.6.0rc1 (default, Dec 10 2016, 14:50:33)
[GCC 6.2.1 20160916 (Red Hat 6.2.1-2)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import marrow.util
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'marrow.util'
>>>

当我尝试在 Mock 中将 marrow.mailer 构建为 RPM 包时,我发现了这个问题。使用 Python 2.7 和 3.5 一切正常,但 Python 3.6 无法从站点包导入 marrow.util,因此 marrow.mailer 的测试在 RPM 构建期间失败。

失败测试的回溯示例:

Traceback:
test/test_addresses.py:8: in <module>
from marrow.mailer.address import Address, AddressList, AutoConverter
marrow/mailer/__init__.py:12: in <module>
from marrow.mailer.message import Message
marrow/mailer/message.py:21: in <module>
from marrow.mailer.address import Address, AddressList, AutoConverter
marrow/mailer/address.py:12: in <module>
from marrow.util.compat import basestring, unicode, unicodestr, native
E ModuleNotFoundError: No module named 'marrow.util'

我在 Python 3.6 的变更日志中找不到与此问题相关的任何内容。

感谢您的帮助。

编辑:我已经在 Python 3.6 中检查了 sys.path,一切看起来都不错:

$ python3.6
Python 3.6.0rc1 (default, Dec 10 2016, 14:50:33)
[GCC 6.2.1 20160916 (Red Hat 6.2.1-2)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.path
['', '/usr/lib64/python36.zip', '/usr/lib64/python3.6', '/usr/lib64/python3.6/lib-dynload', '/usr/lib64/python3.6/site-packages', '/usr/lib/python3.6/site-packages']
>>>

编辑 2:

因为我仍然找不到任何解决方案并且我没有任何回应,所以我创建了一个简单的 Bash 脚本来重现我的情况。您唯一需要的是 Python 3.5 和 Python 3.6。

#!/bin/bash

# Change this to run script with different Python
#PYTHON=python3.5 # system Python 3.5
PYTHON=~/temp/Python-3.6.0/python # compiled Python 3.6

# Create venv and activate
$PYTHON -m venv venv
source ./venv/bin/activate

# Install marrow.util package as a part of namespace package marrow
pip install marrow.util

# Create simple folder structure
mkdir -p marrow/mailer

# Create structure of __init__.py files
# For namespace package with related content
cat >> marrow/__init__.py << EOL
try: # pragma: no cover
__import__('pkg_resources').declare_namespace(__name__)
except ImportError: # pragma: no cover
__import__('pkgutil').extend_path(__path__, __name__)
EOL

# For mailer module just with print()
cat >> marrow/mailer/__init__.py << EOL
print('Imported!!!')
EOL

# Testing
# Importing marrow.util installed via pip in venv
$PYTHON -c "import marrow.util"
# Importing marrow.mailer created manually in PWD
$PYTHON -c "import marrow.mailer"

# deactivate venv
deactivate

如果您使用 Python 3.5 执行此脚本,您将看到 Python 3.5 可以导入通过 pip 安装的 marrow.util 但无法导入本地文件夹中的 marrow.mailer .但是Python 3.6 可以导入本地模块marrow.mailer 而不能导入模块marrow.util

最佳答案

这些包没有使用隐式命名空间(“ native 命名空间”),或者如果您有使用隐式命名空间的版本,请固定您的依赖项以确保您不会混合使用新旧样式命名空间。它们是完全不相容的方法。

在您的 MCVE 示例代码中,您似乎试图构建一个 namespace 包(marrow/__init__.py 通过旧的 Python 2 显式声明替换技巧声明),又名。 pkg-resources-style namespace packages .这需要一个参数到 setup.py(实际打包)并通过包安装安装元数据。具体来说,如果“开发中”安装并解压/解压到安装路径。没有它,就没有真正的 namespace ,并且您的代码将找不到,而不是使用这种旧样式。 (第一个,已安装的,将获胜。)

在 REPL 中,您可以导入命名空间,例如import marrow,然后检查 marrow.__path__ 以查看作为诊断辅助工具发现/包含的内容;我当前在这台机器上的 WIP 虚拟环境有 m.packagem.schemam.interface,这对我来说很有意义最近一直在构建这些版本。更现代的方法 native namespacing确实允许更自由形式的混合,没有 __init__.py 的文件夹只是 一个命名空间,自动合并到 PYTHONPATH,但这不是命名空间过去的工作方式,唉。 (所有参与者都需要 stub __init__.py,所有命名空间级别都没有其他代码。)

我正在对整个 Marrow 生态系统进行现代化改造(如上所述,我已经开始了一些)以消除 Python 2 遗留问题并开始采用新的 Python 3 结构和方法,包括现代命名空间。对于仍然需要旧命名空间或在 Python 2 上的任何代码,所有内容和依赖项的主要版本提升应保持小于这些版本。

(我正在重新获取本地 Python 3.6 和 3.5 以进一步调查。)

关于Python 3.6.0 隐式命名空间包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41302558/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com