1

I'm doing a functools.partial(print, flush=True) in the C-API before calling PyRun_File (please see Python C-API and PyRun_File: Using "import functools and partial(print, flush=True)").

The print works in the __main__ module, but isn't available in imported modules.

I'll try to create a simple example to describe the issue:

C-code

Please see full code example in https://stackoverflow.com/questions/67875182/ ... ... PyObject* newPrint = PyObject(partial, args, kwargs); PyObject* main_module = PyImport_ImportModule("__main__"); PyObject* pdict = PyModule_GetDict(main_module); PyDict_SetItemString(pdict, "print", newPrint); FILE* fp = fopen("prg_1.py", "r"); PyObject* pval = PyRun_File(fp, "prg_1.py", Py_file_input, pdict, pdict); 

And the Python files:

prg_1_func.py

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

prg_1.py

import prg_1_func if __name__ == "__main__": print("Start...") prg_1_func.execute() print("...End") 

The new print function is available in __main__ due to the call to PyDict_SetItemString(pdict, "print", newPrint).

But how can I get it to be "visible" in prg_1_func.py as well?

I can not/do not want to edit any of the Python files!

I came up with one idea but have no clue if it is even achievable, i.e. import everything and postpone the actual execution of the code?

PyObject* newPrint = PyObject(partial, args, kwargs); PyObject* main_module = PyImport_ImportModule("__main__"); PyObject* pdict = PyModule_GetDict(main_module); Read all modules that will be imported, without executing the code! for all modules as MOD do: PyDict_SetItemString(pdict, MODname + ".print", newPrint); FILE* fp = fopen("prg_1.py", "r"); PyObject* pval = PyRun_File(fp, "prg_1.py", Py_file_input, pdict, pdict); 

If anyone else has encountered the same or a similar problem and has managed to solve it, how did you do it? :o)

3
  • If you want to overwrite print for the entire program, you have to do so in builtins. That's not at all related to the C-API, though. Are you able to do this in pure Python without jumping through the hoops of the C-API? The error in your previous question would already have been the same in pure Python and the C-API, the C-API was just obfuscating things. Commented Jun 8, 2021 at 11:34
  • Does this answer your question? Python 3 - substituting functions for print() Commented Jun 8, 2021 at 11:43
  • Thank you, @MisterMiyagi! I can not change any Python file at all (as I have no control over a vast majority of them) and the Python code is run from a C program with PyRun_File, which is why I tried to do the functools.partial(print, flush=True) before calling PyRun_File. With the help from DavidW it did work, until I encountered the problem I've stated in this question. The info and the link you provided might point me in the right direction, so I will have a look. Commented Jun 8, 2021 at 12:13

1 Answer 1

0

Thank you, MisterMiyagi, for pointing me in the right direction!

If you have a similar problem, please follow the link provided in the comments section in the first post, and hopefully it will help you as well.

The solution to have print = functools.partial(print, flush=True) act globally across modules seems to be (error checking omitted):

Py_Initialize(); 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_SetAttrString(builtins, "print", newPrint); <--- PyObject* main_module = PyImport_ImportModule("__main__"); PyObject* pdict = PyModule_GetDict(main_module); FILE* fp = fopen("prg_1.py", "r"); PyObject* pval = PyRun_File(fp, "prg_1.py", Py_file_input, pdict, pdict); Py_Finalize(); 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.