次のファイル階層があります。
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(), "."])])