如何使用C api以完整路径导入文件?

时间:2009-11-25 13:31:25

标签: python python-c-api

PyObject * PyImport_ImportModule(const char * name)

如何指定完整的文件路径和模块名称?

PyImport_SomeFunction(const char *path_to_script, const char *name)

谢谢, 利亚

6 个答案:

答案 0 :(得分:3)

所有* .py文件位于一个目录中的情况的另一种解决方案:

PySys_SetPath("path/with/python/files");
PyObject *pModule = PyImport_ImportModule("filename_without_extension");

答案 1 :(得分:2)

我不能给你一个完整的答案,但我想我可以给你一个开始的地方。 Python提供了一个名为imp的内置模块,它提供了对导入内部的访问。它包含一个函数load_module(),它允许您传入路径。这是在Python/import.c中实现的;只需搜索imp_load_module

答案 2 :(得分:2)

正如所指出的,使用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>" );

要引用当前目录,只需使用"."作为文件夹路径。

答案 3 :(得分:1)

最终,我最终使用了imp模块中的load_source:

s.sprintf( 
  "import imp\n" 
  "imp.load_source('%s', r'%s')", modname, script_path); 
PyRun_SimpleString(s.c_str()); 

我认为这是最可行的解决方案。欢迎提出其他建议。

答案 4 :(得分:1)

CPython将not hesitate通过imp模块进行调用以执行导入作业,因此您没有理由不自行执行此操作。

这是在C ++中实现此目的的一种方法,其中modulePathmoduleName因懒惰而成为单独的变量:

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;
}

我是基于one of my projects' Python module loader编写的,它使用了更高级的引用计数管理,我没有尝试过这个,所以使用风险自负。

答案 5 :(得分:0)

我验证了stesim的替代方案。

无论使用哪种解决方案,重要的是要提到在Windows上使用斜杠而不是反斜杠来获取完整路径非常重要。

path = "C:\\path\\to\\module\\module.py" // wrong
path = "C:/path/to/module/module.py"     // correct

在其他一些问题和答案(如Windows path in python)中指出,第一个变体也应该起作用。无论我尝试什么方法,我都无法以这种方式工作。