8

Python 3.6.0rc1 の暗黙的な名前空間パッケージで奇妙な動作を発見しました。私が間違っているのか、それとも Python 3.6 のバグなのか教えてください。

marrow2 つの別個のパッケージmarrow.utilmarrow.mailer. 2 番目のものは最初のものに依存します。

Python 2.7、3.5、および 3.6 用にmarrow.utilインストールしたとします。site-packages

$ 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名前空間パッケージの 2 番目の部分を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'
>>> 

marrow.mailerMock で 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 の Changelog で、この問題に関連するものを見つけることができません。

助けてくれてありがとう。

編集:sys.path 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 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 はmarrow.utilpip 経由でインストールされたものをインポートできmarrow.mailerますが、ローカル フォルダーにはインポートできないことがわかります。しかし、Python 3.6 はローカル モジュールmarrow.mailerをインポートできますが、モジュールをインポートすることはできませんmarrow.util

4

1 に答える 1

2

これらのパッケージは、暗黙的な名前空間 (「ネイティブ名前空間」) を使用していません。または、使用しているバージョンがある場合は、依存関係を固定して、古いスタイルの名前空間と新しいスタイルの名前空間が混在しないようにしてください。それらはまったく相容れないアプローチです。

marrow/__init__.pyMCVE サンプル コードで、名前空間パッケージ (古い Python 2 の明示的な宣言置換トリックを使用して宣言)、AKA pkg-resources-style namespace packagesを構築しようとしているようです。これには、(実際のパッケージ化) への引数と、setup.pyパッケージのインストールによるメタデータのインストールが必要です。具体的には、この方法には、「開発中」にインストールされている場合.pthのファイル トリック (参照) と、インストールのためにそのパスへの抽出/アンパックが含まれます。$VIRTUAL_ENV/lib/python3.?/site-packagesそれがなければ、実際には名前空間が存在せず、この古いスタイルではなく、コードが見つかりません。(最初にインストールされたものが勝ちます。)

import marrowREPL では、名前空間をインポートすることができますmarrow.__path__。このマシン上の現在の WIP 仮想環境にはm.packagem.schema、およびがありm.interface、これらのリリースを最近ビルドしているので、これは理にかなっています。ネイティブ名前空間へのより現代的なアプローチは、より自由な形式の混合を可能にします。just のないフォルダー__init__.py名前空間であり、自動的にPYTHONPATH. __init__.py(すべての参加者は、すべての名前空間レベルで他のコードが存在しないスタブを必要とします。)

私は現在、Marrow エコシステム全体を最新化する過程にあり (上記のように、すでにいくつかのエコシステムから始めています)、Python 2 のレガシーを排除し、最新の名前空間を含む新しい Python 3 構造とアプローチを採用し始めています。すべてのメジャー バージョン バンプと依存関係は、まだ古い名前空間を必要とするコードや Python 2 でこれらのバージョンよりも少なくピン留めする必要があります。

(さらに調査するために、ローカルの Python 3.6 および 3.5 を再取得しています。)

于 2019-04-28T15:27:55.307 に答える