Ich suchte nach einer Möglichkeit, einen externen Prozess über ein Python-Skript auszuführen und seine Standardnachrichten während der Ausführung zu drucken.
Der folgende Code funktioniert, druckt jedoch zur Laufzeit keine Standardausgabe. Beim Beenden wird folgende Fehlermeldung angezeigt:
sys.stdout.write (nächste Zeile) TypeError: muss str sein, keine Bytes
p = subprocess.Popen(["demo.exe"],stdout = subprocess.PIPE, stderr= subprocess.PIPE)
# Poll process for new output until finished
while True:
nextline = p.stdout.readline()
if nextline == '' and p.poll() != None:
break
sys.stdout.write(nextline)
sys.stdout.flush()
output = p.communicate()[0]
exitCode = p.returncode
Ich benutze Python 3.3.2
Antworten:
Python 3 behandelt Strings etwas anders. Ursprünglich gab es nur einen Typ für Zeichenfolgen :
str
. Als Unicode in den 90er Jahren an Bedeutung gewann, wurde der neueunicode
Typ hinzugefügt, um Unicode zu handhaben, ohne den bereits vorhandenen Code 1 zu beschädigen . Dies ist praktisch dasselbe wie,str
jedoch mit Multibyte-Unterstützung.In Python 3 gibt es zwei verschiedene Typen:
bytes
Typ. Dies ist nur eine Folge von Bytes. Python weiß nichts darüber, wie man dies als Zeichen interpretiert.str
Typ. Dies ist auch eine Folge von Bytes, aber Python weiß, wie diese Bytes als Zeichen interpretiert werden .unicode
Typ wurde gelöscht.str
unterstützt jetzt Unicode.In Python 2 kann die implizite Annahme einer Codierung viele Probleme verursachen. Möglicherweise verwenden Sie die falsche Codierung, oder die Daten haben möglicherweise überhaupt keine Codierung (z. B. ein PNG-Bild).
Python explizit zu sagen, welche Codierung verwendet werden soll (oder explizit zu raten), ist oft viel besser und entspricht viel mehr der "Python-Philosophie" von " explizit ist besser als implizit ".
Diese Änderung ist nicht mit Python 2 kompatibel, da sich viele Rückgabewerte geändert haben, was zu subtilen Problemen wie diesem führt. Dies ist wahrscheinlich der Hauptgrund, warum die Einführung von Python 3 so langsam war. Da Python keine statische Typisierung 2 hat, ist es unmöglich, dies automatisch mit einem Skript (wie dem gebündelten
2to3
) zu ändern .str
zubytes
mitbytes('h€llo', 'utf-8')
; das sollte produzierenb'H\xe2\x82\xacllo'
. Beachten Sie, wie ein Zeichen in drei Bytes konvertiert wurde.bytes
zustr
mitb'H\xe2\x82\xacllo'.decode('utf-8')
.Natürlich ist UTF-8 in Ihrem Fall möglicherweise nicht der richtige Zeichensatz. Verwenden Sie daher unbedingt den richtigen.
In Ihrem spezifischen Code
nextline
ist vom Typbytes
, nichtstr
vom Lesenstdout
undstdin
vonsubprocess
in Python 3 vonstr
bis geändertbytes
. Dies liegt daran, dass Python nicht sicher sein kann, welche Codierung dies verwendet. Es verwendet wahrscheinlich dasselbe wiesys.stdin.encoding
(die Codierung Ihres Systems), kann aber nicht sicher sein.Sie müssen ersetzen:
mit:
sys.stdout.write(nextline.decode('utf-8'))
oder vielleicht:
Sie werden auch ändern müssen ,
if nextline == ''
umif nextline == b''
da:>>> '' == b'' False
Siehe auch Python 3 ChangeLog , PEP 358 und PEP 3112 .
1 Es gibt einige nette Tricks, die Sie mit ASCII machen können, die Sie mit Multibyte-Zeichensätzen nicht machen können. Das bekannteste Beispiel ist das "xor mit Leerzeichen zum Umschalten der Groß-
chr(ord('a') ^ ord(' ')) == 'A'
und Kleinschreibung" (z. B. ) und "Setzen Sie das 6. Bit, um ein Steuerzeichen zu erstellen" (zord('\t') + ord('@') == ord('I')
. B. ). ASCII wurde in einer Zeit entwickelt, in der die Manipulation einzelner Bits eine Operation mit nicht zu vernachlässigenden Auswirkungen auf die Leistung war.2 Ja, Sie können Funktionsanmerkungen verwenden, aber es ist eine vergleichsweise neue Funktion, die nur wenig verwendet wird.
quelle
demo.exe
Ausgaben und was genau Sie wollen, ist es schwierig, Ihre Frage zu beantworten, da nicht klar ist, was die Frage ist :-) Beachten Sie jedoch, dassreadline()
eine Zeile gelesen wird , das heißt, sie liest weiter, bis sie auf eine neue Zeile stößt. was unter Windows, glaube ich, ist\r\n
und nicht\n
demo.exe
Ausgänge\r\n
Zeilenende, und dasdemo.exe
ist auch stdout Spülung.Während die akzeptierte Antwort gut funktioniert, wenn die Bytes, die Sie aus Ihrem Unterprozess haben, mit
sys.stdout.encoding
(oder einer kompatiblen Codierung, wie das Lesen von einem Tool, das ASCII ausgibt und Ihr Standardout UTF-8 verwendet) codiert werden , ist die richtige Methode, beliebige Bytes in Standardausgabe zu schreiben ist:Dadurch werden die Bytes einfach so ausgegeben, wie sie sind, ohne zu versuchen, sie als Text-in-Some-Codierung zu behandeln.
quelle