将嵌入式Python IO重定向到使用AllocConsole创建的控制台

时间:2009-11-09 00:07:45

标签: python console io-redirection

我在将Python IO重定向到我为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,BTW)并删除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 :(得分:9)

在Python端设置sys.stdout(可能是open('CONOUT$', 'wt'))以使Python print工作,同样适用于sys.stderrsys.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')

答案 1 :(得分:1)

告诉嵌入式python将其输出重定向到文件要容易得多。

试试这段代码:

PyRun_SimpleString("import sys\n");
PyRun_SimpleString( "sys.stdout = sys.stderr = open(\"C:\\embedded_log_file.txt\", \"w\")\n" );