4

次のファイル階層があります。

python/apps/A.py
      /geometrylib/__init__.py
      /geometrylib/B.py
      /geometrylib/geometry.py
      /geometrylib/goemetry.pyx
      /geometrylib/goemetry.pyd

geometry.pyx と geometry.py には同じクラス Camera が含まれています (cython バージョンは cdef でクラスを定義しています)。A.py と B.py の両方がジオメトリ モジュールをインポートします。

cython バージョン (geometry.pyd にコンパイルされたもの) をインポートすると、python/geometrylib フォルダーの B.py 内から Camera を正しく pickle できます。しかし、python/apps フォルダーの A.py から Camera をピクルすることはできません。次の例外が発生します。

pickle.PicklingError: ピクルできません: geometry.Camera として見つかりません

ただし、geometry.pyd を削除し、代わりに python バージョン (geometry.py) をインポートすると、A.py または B.py から Camera を pickle できます。どちらの場合も同じフォルダーから実行される同じpythonコマンドラインであるgeometry.pydを削除することを除けば、他に何も変更はありません。 なぜこの違い?

少し掘り下げると、 C:\Python27\Lib\pickle.py 行 742 で例外が発生することがわかります

try:
    __import__(module)            #line 742
    mod = sys.modules[module]
    klass = getattr(mod, name)
except (ImportError, KeyError, AttributeError):
    raise PicklingError(
        "Can't pickle %r: it's not found as %s.%s" %
        (obj, module, name))

A.py で cython バージョン (geometry.pyd) をインポートすると (そして期待をトリガーするために Camera インスタンスをピクルします)、モジュールは「ジオメトリ」であり__import__(module)、例外をトリガーします。A.py で Python バージョン (geometry.py) をインポートすると (そして期待をトリガーするために Camera インスタンスをピクルします) モジュールは "geometrylib.geometry" であり__import__(module)、モジュールを正しくインポートします。

python/geometrylib を PYTHONPATH に追加することで問題を解決しました。次に、cython バージョンを使用して、A.py と B.py の両方から Camera を正しく pickle できます。

これはどのように機能するはずですか?私は自分の解決策が好きではありません。誰かがより良い解決策を持っていますか?

いくつかの追加情報を追加するために編集されました。

また、リクエストにより、これは私が cython 拡張機能をビルドするために使用した setup.py です。

from distutils.core import setup
from distutils.extension import Extension
from Cython.Distutils import build_ext
import numpy

setup(
    cmdclass = { 'build_ext': build_ext},
    ext_modules = [Extension("geometry", ['geometry.pyx'], include_dirs=[numpy.get_include(), "."])])
4

1 に答える 1

4

geometry.pyx をトップレベル モジュールとして構築していますが、実際にはgeometrylibパッケージの一部です。その結果、Cameraクラスには(の代わりに) 誤った__module__値が割り当てられ、pickler は という名前の最上位モジュールを見つけようとして失敗します。geometrygeometrylib.geometrygeometry

標準のパッケージング ガイドラインに従う必要があります。つまり、setup.py を「Python」フォルダの最上位モジュール (geometrylib) の隣に置きます。setup 呼び出しは次のようになります。

setup(
    cmdclass = {'build_ext': build_ext},
    ext_modules = [Extension("geometrylib.geometry", ['geometrylib/geometry.pyx'], include_dirs=[numpy.get_include(), "."])])
于 2013-05-06T18:56:57.340 に答える