3

120MB のデータ ファイルをロードする必要がある Python 用の C 拡張機能を作成してインストールしようとしています。distutilspackage_data引数を使用して、拡張モジュールと同じフォルダーにデータ ファイルを正しくインストールしました。ただし、C コードはデータ ファイルを見つける方法を知りません。

インストールされたデータ ファイルへのパスを C 拡張子でハード コードすることはできますが (これは機能します)、インストール ディレクトリが異なるシステムでは明らかに機能しません。この拡張機能は、Linux と Windows の両方にインストールする必要があります。

モジュールへのパスを取得し、そこからデータファイルへのパスを作成するために使用しようとしましPyModule_GetFilename()たが、その関数はSystemError: module filename missing. おそらくエラーは、モジュールの init 関数内で呼び出そうとしているためですか?

必要に応じて、モジュールの初期化以外でデータ ファイルを手動で読み込むことができますが、インポート時にファイルを自動的に読み込む方がはるかに望ましいでしょう。

編集:だから、回避策を見つけました。ファイルのパスを引数として取ることができる初期化関数を書きました。Python からモジュールの__file__属性にアクセスし、そこからデータ ファイルへのパスを特定できます。次に、で初期化関数を実行すると、すべてが機能し__init__.pyます。これはうまくいきますが、誰かがもっとエレガントな解決策を教えてくれることを願っています。

4

1 に答える 1

0

それで、私は自分でもう少し良い解決策を思いついたので、他の人に役立つ場合に備えて投稿すると思いました.

my_module私のプロジェクトは、C 拡張子を持つパッケージ ( ) で構成されています。インストールには、、、およびが含ま_my_extension.so__init__.pyますdatafile.dat。関連部分では、__init__.py次のようになります。

import os

def datafile_path():
    return os.path.join(os.path.dirname(__file__), "datafile.dat")

import _my_extension

私の C 拡張機能の初期化関数は次のようになります。

PyMODINIT_FUNC
init_my_extension(void)
{
    PyObject *m, *fileobj, *pModule, *pFunc;

    m = Py_InitModule3("_my_extension", _my_extension_methods, "A docstring");
    if (m == NULL)
        return;

    pModule = PyImport_ImportModule("my_module");
    pFunc = PyObject_GetAttrString(pModule, "datafile_path");
    fileobj = PyObject_CallFunction(pFunc, NULL);
    Py_DECREF(pFunc);

    LoadDataFile(PyString_AS_STRING(fileobj));

    Py_DECREF(fileobj);
    Py_DECREF(pModule);
}

明らかにエラー処理を追加する必要がありますが、これはまだ少しずれているように見えますが、少なくともモジュールの初期化時にデータ ファイルをロードして動作します。明らかにdatafile_path、私は C で多くの計算を行うことができましたが、とにかくモジュールをインポートする必要があり、クロスプラットフォームの互換性が必要であるため、モジュールを使用する方が簡単に思えましたos

とにかく、誰かがこれをもっとうまくやる方法を教えてくれたら嬉しいので、これを開いたままにしますが、より良い答えがない場合に備えて、同じ問題を抱えている人を助けるために両方の答えを出すと思いました問題が明確になるかもしれないと思ったからです。

于 2012-06-14T15:24:57.467 に答える