将嵌入式Python IO重定向到使用AllocConsole创建的控制台 [英] Redirect Embedded Python IO to a console created with AllocConsole

查看:715
本文介绍了将嵌入式Python IO重定向到使用AllocConsole创建的控制台的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些麻烦让Python IO重定向到我为我的Win32应用程序分配的控制台。是否有一个特定于Python的流,我需要重定向?



这里是更多或更少,我现在做的错误检查删除等: / p>

  int __stdcall WinMain(/ *这里常用的东西* /){
//创建控制台
AllocConsole ();
SetConsoleTitle(L我的控制台);

//重定向标准IO流到新控制台
freopen(CONOUT $,w,stdout);
freopen(CONOUT $,w,stderr);
freopen(CONIN $,r,stdin);

//测试控制台:
printf(This Works.\r\\\
);
cout<< 所以这个< endl;

// Python Stuff(这是失败的地方)
Py_Initialize();
PyRun_SimpleString(print('I do not work。')\\\
);
Py_Finalize();如果我运行相同的东西,但作为一个控制台应用程序(Visual Studio 05,
}



< BTW)并删除AllocConsole调用一切正常。任何人都知道我错过了什么?



编辑:为了澄清,我正在寻找一种方法来从C API。



YET ANOTHER编辑: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)){
/ *向全世界公布你的错误* /
}
Py_DECREF
Py_DECREF(io);
Py_DECREF(pystdout);


解决方案

设置 sys.stdout 在Python端(可能是 open('CONOUT $','wt') / code>工作,类似 sys.stderr sys.stdin 。 (有更快的方法使这个发生从C扩展,但最简单的方法是只是执行Python语句,一个 import sys 在前面 - )。 / p>

原因:因为Python的运行时,在启动时发现标准FD关闭,因此设置 sys.stdout 并且不会再检查和设置它们不同 - 所以你只是自己设置它们,明确地,它会很好。



如果你渴望做它所有在C-API级别,它将需要几行,但是当然可以做...

  PyObject * sys = PyImport_ImportModule(sys); 
PyObject * pystdout = PyFile_FromString(CONOUT $,wt);
if(-1 == PyObject_SetAttrString(sys,stdout,pystdout)){
/ *引发错误和非常响亮* /
}
Py_DECREF
Py_DECREF(pystdout);

这完全等同于单个Python行:

  sys.stdout = open('CONOUT $','wt')

$ b b

I am having some trouble getting Python IO redirected to a console that I've allocated for my Win32 app. Is there a Python-specific stream that I need to redirect?

Here's more-or-less what I'm doing now (error checking removed, etc.):

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();
}

If I run the same thing but as a console app (Visual Studio 05, BTW) and remove the AllocConsole call everything works. Anyone know what I'm missing?

EDIT: Just for clarification, I am looking for a way to do it from the C API.

YET ANOTHER EDIT: Alex's solution is correct, but for anyone out there using Python 3.x you'll probably notice that the PyFile_FromString function is missing in the new API. While it may not be the best alternative, I found that this works fine in 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);

解决方案

Set sys.stdout on the Python side (presumably to an open('CONOUT$', 'wt')) to make Python's print work, and similarly for sys.stderr and sys.stdin. (There are faster ways to make this happen from a C extension, but the simplest way is to just execute the Python statements, with a import sys in front;-).

Why: because Python's runtime, on startup, found the standard FDs closed, set sys.stdout and friends accordingly, and is not going to check again and set them differently -- so you just set them yourself, explicitly, and it will be fine.

If you're keen to do it all at C-API level, it will take a few lines, but of course it can be done...

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);

this is the exact equivalent of the single Python line:

sys.stdout = open('CONOUT$', 'wt')

这篇关于将嵌入式Python IO重定向到使用AllocConsole创建的控制台的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆