PyObject* PyImport_ImportModule( const char *name)
代わりにフルファイルパスとモジュール名を指定するにはどうすればよいですか?
のようにPyImport_SomeFunction(const char *path_to_script, const char *name)
。
PyObject* PyImport_ImportModule( const char *name)
代わりにフルファイルパスとモジュール名を指定するにはどうすればよいですか?
のようにPyImport_SomeFunction(const char *path_to_script, const char *name)
。
すべての *.py ファイルが 1 つのディレクトリにある場合の別の解決策:
PySys_SetPath("path/with/python/files");
PyObject *pModule = PyImport_ImportModule("filename_without_extension");
指摘したように、AlexP による上記のソリューションを使用すると、指定されたディレクトリの外にモジュールをインポートすることはできません。ただし、パスを設定する代わりに、モジュールを検索するパスを追加できます。これは、そのパスをsys.pathに追加することで実行できます。残念ながら、C API はそれを直接実行できる関数を公開していません。代わりに、Python 自体にそれを行うように依頼することができます。
PyRun_SimpleString( "import sys\nsys.path.append(\"<insert folder path>\")\n" );
または同等のもの: (警告: 未テスト)
PyObject* sys = PyImport_ImportModule( "sys" );
PyObject* sys_path = PyObject_GetAttrString( sys, "path" );
PyObject* folder_path = PyUnicode_FromString( "<insert folder path>" );
PyList_Append( sys_path, folder_path );
<insert folder path>/<file>.py
これで、通常の方法で任意のファイルをインポートできます
PyObject* mymodule = PyImport_ImportModule( "<file>" );
現在のディレクトリを参照するには、単に"."
フォルダー パスとして使用します。
最終的に、imp モジュールの load_source を使用することになりました。
s.sprintf(
"import imp\n"
"imp.load_source('%s', r'%s')", modname, script_path);
PyRun_SimpleString(s.c_str());
最も現実的な解決策だと思います。他の提案は大歓迎です。
完全な回答はできませんが、出発点を示すことはできると思います。Python は、imp
インポート内部へのアクセスを提供する と呼ばれる組み込みモジュールを提供します。パスを渡すことができる関数 load_module() が含まれています。これはPython/import.cで実装されています。を検索するだけですimp_load_module
。
CPython はインポート ジョブを実行するためにモジュールを介して呼び出すことを躊躇imp
しません。そのため、自分で実行しない理由はありません。
C++ でこれを行う 1 つの方法を次に示します。ここで、modulePath
とmoduleName
は遅延のために別の変数です。
PyObject* loadModule(const char* modulePath, const char* moduleName)
{
auto modules = PyImport_GetModuleDict();
auto impModule = PyDict_GetItemString(modules, "imp");
if (impModule)
{
// GetItemString returns a borrowed reference, but ImportModule
// returns a new reference, so INCREF here to even it out
Py_INCREF(impModule);
}
else
{
impModule = PyImport_ImportModule("imp");
if (!impModule)
{
// we've tried hard enough, bail out
PyErr_Print();
return nullptr;
}
}
// The Python API asks for non-const char pointers :(
char methodName[] = "load_source";
char args[] = "ss";
auto module = PyObject_CallMethod(impModule, methodName, args, moduleName, modulePath);
Py_XDECREF(impModule);
Py_XDECREF(modulePath);
return module;
}
私はこれを私のプロジェクトの Python モジュール loader の 1 つに基づいて書きました。これはより手の込んだ refcount 管理を使用しますが、これは試していないので、自己責任で使用してください。