【问题标题】:Python C-API and PyRun_File: Using "import functools and partial(print, flush=True)"Python C-API 和 PyRun_File:使用“import functools and partial(print, flush=True)”
【发布时间】:2021-08-24 17:57:16
【问题描述】:

首先是一个简短的背景:

(1) 在Python3.6中运行这个程序需要等到它结束才能显示结果:

import time

for i in range(5):
        print(i, end=" ")
        time.sleep(1)

(2) 另一方面,这个程序按我的意愿工作,每秒打印每个值:

import time

import functools
print = functools.partial(print, flush=True)

for i in range(5):
        print(i, end=" ")
        time.sleep(1)

现在我的问题是:

如何添加

import functools
print = functools.partial(print, flush=True)

在 C 代码中,以便我可以使用 PyRun_File 运行程序 1,但结果就像我在运行程序 2 一样?

我在查找简单易懂的文档和示例时遇到了麻烦,因此希望能得到一些帮助。

这是我尝试过的(省略了错误检查,并且我正在尝试改进的程序中已有的旧代码标记为“//existing”):

Py_Initialize(); //existing

PyObject* functools = PyImport_ImportModule("functools");
PyObject* partial = PyObject_GetAttrString(functools, "partial");

PyObject* builtins = PyImport_ImportModule("builtins");
PyObject* print = PyObject_GetAttrString(builtins, "print");

PyObject* args = PyTuple_New(1);
PyTuple_SetItem(args, 0, print);

PyObject* kwargs = PyDict_New();
PyDict_SetItemString(kwargs, "flush", Py_True);

PyObject_Call(partial, args, kwargs);

PyObject* main_module = PyImport_ImportModule("__main__"); //existing
PyObject* pdict = PyModule_GetDict(main_module); //existing

FILE* fp = fopen("prg_1.py", "r"); //existing
PyObject* pval = PyRun_File(fp, "prg_1.py", Py_file_input, pdict, pdict); //existing

Py_Finalize(); //existing

不幸的是,这并没有像我希望的那样工作,所以任何人都可以发现任何明显的错误,或者可能不是那么明显的错误?

提前感谢您的帮助!

【问题讨论】:

  • 对于返回PyObject*每个函数,您应该检查返回值是否为NULL。如果是,那么您需要PyErr_Print 之类的东西来调查原因。这将帮助您找出我们出了什么问题。这可能是模块搜索路径的问题(但如果你知道它失败的地方会更清楚)
  • 感谢您的回复,@DavidW。正如我所写的,我故意在发布的代码中省略了错误处理以使其更清晰。实际上,我当然已经检查了 NULL 并且代码在这个意义上“工作”,但它不起作用。
  • PyObject_Call 有返回值吗?
  • 是的。 tp_name 是“functools.partial”,还有其他 tp_-values 似乎一切正常。作为旁注: PyRun_SimpleString("import functools"); PyRun_SimpleString("print = functools.partial(print, flush=True)");然后调用 PyRun_File 似乎有效。
  • 我的意思是,仅仅调用 functools.partial(print, flash=True) 并不能替换 print - 而是返回一个你可以调用的函数。

标签: python c python-c-api


【解决方案1】:

感谢 DavidW 的宝贵意见,它现在可以工作了!谢谢!

(我确实遇到了另一个问题,我将在一个新问题中解决。)

添加后的代码现在看起来像这样(仍然省略了错误检查):

Py_Initialize(); //existing

PyObject* functools = PyImport_ImportModule("functools");
PyObject* partial = PyObject_GetAttrString(functools, "partial");

PyObject* builtins = PyImport_ImportModule("builtins");
PyObject* print = PyObject_GetAttrString(builtins, "print");

PyObject* args = PyTuple_New(1);
PyTuple_SetItem(args, 0, print);

PyObject* kwargs = PyDict_New();
PyDict_SetItemString(kwargs, "flush", Py_True);

PyObject* newPrint = PyObject_Call(partial, args, kwargs);

PyObject* main_module = PyImport_ImportModule("__main__"); //existing
PyObject* pdict = PyModule_GetDict(main_module); //existing

PyDict_SetItemString(pdict, "print", newPrint);

FILE* fp = fopen("prg_1.py", "r"); //existing
PyObject* pval = PyRun_File(fp, "prg_1.py", Py_file_input, pdict, pdict); //existing

Py_Finalize(); //existing

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-08-30
    • 2021-03-17
    • 2018-04-02
    • 2013-02-26
    • 2019-04-19
    • 1970-01-01
    • 2016-04-13
    • 1970-01-01
    相关资源
    最近更新 更多