4

使用 Python C API 从文件中导入 Python 模块相对容易,PyImport_Import()但是我需要使用存储在字符串中的函数。有没有办法从字符串中导入 python 模块(澄清:没有文件;代码在字符串中)还是我必须将字符串保存为临时文件?

4

3 回答 3

4

无需使用临时文件。使用此代码:

const char *MyModuleName = "blah";
const char *MyModuleCode = "print 'Hello world!'";
PyObject *pyModule = PyModule_New(MyModuleName);
// Set properties on the new module object
PyModule_AddStringConstant(pyModule, "__file__", "");
PyObject *localDict = PyModule_GetDict(pyModule);   // Returns a borrowed reference: no need to Py_DECREF() it once we are done
PyObject *builtins = PyEval_GetBuiltins();  // Returns a borrowed reference: no need to Py_DECREF() it once we are done
PyDict_SetItemString(localDict, "__builtins__", builtins);

// Define code in the newly created module
PyObject *pyValue = PyRun_String(MyModuleCode, Py_file_input, localDict, localDict);
if (pyValue == NULL) {
    // Handle error
}
else
    Py_DECREF(pyValue);

这是取自真实商业应用程序的代码(我通过删除错误处理和其他不需要的细节对其进行了轻微修改)。只需在其中设置所需的模块名称MyModuleName和 Python 代码MyModuleCode即可!

于 2017-03-17T09:17:37.317 回答
1

如果我的理解是正确的,您可以使用PyImport_ImportModulewhichconst char* name来指定要导入的模块。

由于我的理解不正确:

通常将内容转储到.py文件然后执行它们会更好,PyRun_File但是,如果您有字符串并且想要使用那些我猜您可以使用Py_CompileString将其编译为代码对象,然后将其提供PyEval_EvalCode给评估。

于 2016-10-01T15:47:53.997 回答
0

我按照 Dimitirs 制定的策略取得了成功。

            Py_Initialize();
            PyObject *module = Py_CompileString(
                // language: Python
                R"EOT(
fake_policy = {
      "maxConnections": 4,
      "policyDir": "/tmp",
      "enableVhostPolicy": True,
      "enableVhostNamePatterns": False,
})EOT",
                "test_module", Py_file_input);
            REQUIRE(module != nullptr);

            PyObject *pModuleObj = PyImport_ExecCodeModule("test_module", module);
            REQUIRE(pModuleObj != nullptr);
            // better to check with an if, use PyErr_Print() or such to read the error

            PyObject *pAttrObj = PyObject_GetAttrString(pModuleObj, "fake_policy");
            REQUIRE(pAttrObj != nullptr);

            auto *entity = reinterpret_cast<qd_entity_t *>(pAttrObj);
            REQUIRE(qd_entity_has(entity, "enableVhostNamePatterns"));  // sanity check for the test input

            // call Py_DecRef s

在写这篇文章时,我使用了https://awasu.com/weblog/embedding-python/calling-python-code-from-your-program/作为另一个参考。

于 2020-11-02T09:44:09.863 回答