将嵌入的Python IO重定向到使用AllocConsole创建的控制台
我在把Python的输入输出重定向到我为我的Win32应用程序分配的控制台时遇到了一些麻烦。请问有没有什么Python特定的流需要我去重定向呢?
现在我大致上是这样做的(错误检查的部分省略了等):
int __stdcall WinMain(/*Usual stuff here*/) {
// Create the console
AllocConsole();
SetConsoleTitle(L"My Console");
// Redirect Standard IO Streams to the new console
freopen("CONOUT$","w",stdout);
freopen("CONOUT$","w",stderr);
freopen("CONIN$","r",stdin);
// Test the console:
printf("This Works.\r\n");
cout << "So Does this" << endl;
// Python Stuff (This is where it fails)
Py_Initialize();
PyRun_SimpleString("print('I don't work.')\n");
Py_Finalize();
}
如果我运行同样的代码,但作为一个控制台应用程序(顺便说一下,是用Visual Studio 05做的),并且去掉AllocConsole的调用,所有的东西都能正常工作。有人知道我漏掉了什么吗?
补充说明:我想知道如何通过C的API来实现这个功能。
又一个补充:Alex的解决方案是正确的,但对于使用Python 3.x的人来说,你可能会发现新API中缺少了PyFile_FromString这个函数。虽然这可能不是最好的替代方案,但我发现这个在Python 3.x中可以正常工作:
PyObject* sys = PyImport_ImportModule("sys");
PyObject* io = PyImport_ImportModule("io");
PyObject* pystdout = PyObject_CallMethod(io, "open", "ss", "CONOUT$", "wt");
if (-1 == PyObject_SetAttrString(sys, "stdout", pystdout)) {
/* Announce your error to the world */
}
Py_DECREF(sys);
Py_DECREF(io);
Py_DECREF(pystdout);
2 个回答
0
直接让嵌入的Python把输出结果保存到一个文件里要简单得多。
试试这段代码:
PyRun_SimpleString("import sys\n");
PyRun_SimpleString( "sys.stdout = sys.stderr = open(\"C:\\embedded_log_file.txt\", \"w\")\n" );
12
在Python中,设置sys.stdout
(通常是用open('CONOUT$', 'wt')
)可以让Python的print
正常工作,sys.stderr
和sys.stdin
也是一样的做法。虽然从C扩展中有更快的方法来实现这个,但最简单的方式就是直接执行Python语句,前面加上import sys
就可以了;-)。
为什么要这样做呢?因为在Python启动时,它发现标准的文件描述符(FD)是关闭的,所以就相应地设置了sys.stdout
等,但它不会再检查一次并重新设置。因此,你只需要自己明确地设置这些,就没问题了。
如果你想在C-API层面上完成这一切,虽然只需要几行代码,但当然是可以做到的……
PyObject* sys = PyImport_ImportModule("sys");
PyObject* pystdout = PyFile_FromString("CONOUT$", "wt");
if (-1 == PyObject_SetAttrString(sys, "stdout", pystdout)) {
/* raise errors and wail very loud */
}
Py_DECREF(sys);
Py_DECREF(pystdout);
这实际上等同于一行Python代码:
sys.stdout = open('CONOUT$', 'wt')