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 文件都在一个目录中时,另一种解决方案:
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++ 中执行此操作的一种方法,由于懒惰,其中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 module loader编写了这个,它使用了更高级的引用计数管理,我还没有尝试过这个,所以使用风险自负。
我验证了stesim的替代方法有效。
无论使用哪种解决方案,重要的是要提到在 Windows 上使用斜杠而不是反斜杠的完整路径很重要。
path = "C:\\path\\to\\module\\module.py" // wrong
path = "C:/path/to/module/module.py" // correct
在其他一些问题和答案(如python 中的 Windows 路径)中,指出第一个变体也应该起作用。无论我尝试什么方法,我都无法让它以这种方式工作。