2009-11-09 5 views
9

Ich habe Probleme, Python IO auf eine Konsole umzuleiten, die ich für meine Win32-App zugewiesen habe. Gibt es einen Python-spezifischen Stream, den ich umleiten muss?Umleiten von eingebetteten Python-IO zu einer mit AllocConsole erstellten Konsole

Hier ist mehr oder weniger, was ich tue jetzt (Fehler entfernt Prüfung usw.):

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

Wenn ich die gleiche Sache laufen, aber als Konsolenanwendung (Visual Studio 05, BTW) und entfernen Sie den AllocConsole Aufruf alles funktioniert. Wer weiß, was ich vermisse?

EDIT: Nur zur Klarstellung, ich bin auf der Suche nach einer Möglichkeit, es von der C-API zu tun.

NOCH EINE ANDERE BEARBEITUNG: Die Lösung von Alex ist korrekt, aber für jeden, der Python 3.x benutzt, werden Sie wahrscheinlich bemerken, dass die Funktion PyFile_FromString in der neuen API fehlt. Es ist zwar nicht die beste Alternative sein kann, fand ich, dass dies in Python 3.x funktioniert gut:

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

Antwort

9

Set sys.stdout auf der Python-Seite (vermutlich zu einem open('CONOUT$', 'wt')) Pythons print Arbeit zu machen, und in ähnlicher Weise für sys.stderr und sys.stdin. (Es gibt schnellere Möglichkeiten, dies durch eine C-Erweiterung zu erreichen, aber die einfachste Art ist, die Python-Anweisungen mit einer import sys vor auszuführen ;-).

Warum: Da Pythons Runtime beim Start die Standard-FDs geschlossen gefunden hat, setze sys.stdout und Freunde entsprechend, und werde sie nicht erneut überprüfen und sie anders setzen - also setze sie einfach selbst, explizit, und es wird gut.

Wenn Sie daran interessiert sind, alles auf C-API-Ebene zu tun, wird es ein paar Zeilen nehmen, aber natürlich kann es geschehen ...

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

dies das genaue Äquivalent der ist einzelne Python-Zeile:

+0

Danke, schätze ich den Hinweis, aber ich denke, ich sollte noch deutlicher gewesen sein: ich nach einem Weg suchen diese über das C-api zu tun. Die Dokumentation für die File/Sys-APIs ist bestenfalls fleckig. Als solcher hatte ich nicht viel Glück, um es selbst herauszufinden. – Toji

+0

OK, lass mich die Antwort dann bearbeiten. –

+0

Dort - zeigte, wie man die eine Python-Zeile in 7+ Zeilen mit der C-API übersetzt (vielleicht mehr, abhängig von Fehlerdiagnose-Anforderungen). (Sehen Sie, warum erfahrene Python- und C-API-Programmierer oft vorschlagen, nur die Python-Codefolge von C auszuführen?). –

1

Es ist viel einfacher, nur dem eingebetteten Python zu sagen, seine Ausgabe in eine Datei umzuleiten.

diesen Code Versuchen:

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