6

boost python を使用してコンパイルされた python モジュールをロードしようとすると、次のインポート エラーが発生します。

ImportError: /path/to/library/libxml2.so.2: symbol gzopen64, version ZLIB_1.2.3.3 not defined in file libz.so.1 with link time reference

奇妙なことに、それが非標準モジュールをインポートする場合、このエラーは表示されません。つまり、他のモジュールをインポートしてからこのモジュールをインポートすると、インポート エラーで失敗します。何が問題なのか、どのようにデバッグするのかわかりません。

編集:問題を正確に表示するには:

$ python -c 'import json, libMYBOOST_PY_LIB' # DOES NOT WORK!!!
Traceback (most recent call last):
  File "<string>", line 1, in <module>
ImportError: path/to/xml_library/libxml2.so: symbol gzopen64, version ZLIB_1.2.3.3 not defined in file libz.so.1 with link time reference
$ python -c 'import libMYBOOST_PY_LIB, json' # WORKS NOW!!!
$

jsonだけでなく、モジュールの前にインポートすると、他のいくつかのモジュールも同じ問題を引き起こします。例えば。urllib2

4

2 に答える 2

5

importステートメントの順序は重要です。

Python 言語リファレンスに記載されているとおり:

モジュールの名前がわかったら (特に指定がない限り、「モジュール」という用語はパッケージとモジュールの両方を指します)、モジュールまたはパッケージの検索を開始できます。最初にチェックされるのはsys.modules、以前にインポートされたすべてのモジュールのキャッシュです。モジュールがそこにある場合は、インポートのステップ (2) で使用されます。

どのモジュールも変更できます:

  • sys.modules- 以前にインポートされたすべてのモジュールのキャッシュ
  • sys.path- モジュールの検索パス

また、インポート フックも変更できます。

インポート フックを使用すると、zip ファイル、あらゆる種類のアーカイブ ファイル、ネットワークなどからモジュールをロードできます。


import libMYBOOST_PY_LIB

このステートメントは確実に変更sys.modulesされ、その依存関係がモジュール キャッシュに読み込まれます。変更する場合もありsys.pathます。boostフレームワーク (例: 、zopedjangorequests...) がバッテリを含めて出荷されること、またはフレームワークが依存するモジュールのコピーと一緒に出荷されることは、実際には非常に一般的です。

  • django同梱品json
  • requests同梱品urllib3

ライブラリがロードするものを正確に確認するには、次を使用できます。

python -v -c 'import libMYBOOST_PY_LIB'
于 2013-08-15T16:22:03.683 に答える
3

問題

問題はオペレーティング システムにあります。Linux ライブラリ (動的にリンクされた共有オブジェクト ライブラリ) は、他のライブラリに依存できます (これも他のライブラリなどに依存できます)。これらの依存ライブラリが正しく解決されていない場合、説明したエラーが発生します。

共有ライブラリとは (so)

複数のオブジェクト ファイルを取得してそれらをリンクすることにより、共有ライブラリを作成できます。リンカーは、共有ライブラリを作成するときに多くのメタ データを保持します。

  1. 再配置テーブル
  2. エクスポートされたシンボル (他のユーザーがアクセスできる関数と変数) のリスト
  3. インポートされたシンボルのリスト (このライブラリが他のライブラリから使用する関数と変数)
  4. インポートされたシンボルを満たすために使用できる他のライブラリのファイル名のリスト

ライブラリが使用されると、システムはライブラリをロードし、再配置テーブルによって参照されるアドレスを変更してから、インポートされたシンボルを見つけようとします。これらの場合、システムは最初にすでにロードされているライブラリをチェックします。これがすべてのシンボルを満たさない場合、ライブラリにリストされているファイル名を見つけて、その名前のファイルが存在するかどうか、有効なライブラリであるかどうか、必要なシンボルをエクスポートするかどうかを確認しようとします。

通常、ここでの「システム」は動的ローダーであり、カーネル空間ではなくユーザー空間で実行されます。

プログラムで使用されているライブラリを確認するにはどうすればよいですか

コマンドでライブラリの内容を確認できますldd

実行中の実行可能ファイルをチェックしたい場合は、lsofをフィルタリングし*.soてチェックしてみてください/proc/[pid]/maps

問題をデバッグする方法

あなたの場合、問題のライブラリがロードされる直前にプログラムを保持します (たとえば、コンソールからの読み取りまたはスリープ コマンドを挿入します)。次に、現在読み込まれているライブラリを確認します。良い場合には、問題のシンボルをエクスポートするライブラリが既にロードされていることがわかります。エラーの場合、このライブラリはロードされず、システムは次のステップで間違った依存ライブラリをロードしようとします (たとえば、必要なシンボルが見つからない別のバージョンのライブラリ)。

ライブラリの順序は重要ですか

通常はありませんが、詳細によって異なります。異なるバージョンで同じライブラリが必要な場合、またはシステムがすべての場合に共有ライブラリを解決できない場合、重要になる可能性があります。残念ながら、これらの問題はデバッグが非常に困難です。Windows では DLL 地獄があり、Linux では共有オブジェクトに似ています。問題のデバッグを頑張ってください!

于 2013-08-19T13:15:06.877 に答える