2013-05-08 10 views
5

I haben die folgenden drei Python Scripts:Der Unterschied zwischen bash und Python Rohre

parent1.py

import subprocess, os, sys 

relpath = os.path.dirname(sys.argv[0]) 
path = os.path.abspath(relpath) 
child = subprocess.Popen([os.path.join(path, 'child.lisp')], stdout = subprocess.PIPE) 
sys.stdin = child.stdout 
inp = sys.stdin.read() 
print(inp.decode()) 

parent2.py:

import sys 
inp = sys.stdin 
print(inp) 

child.py:

print("This text was created in child.py") 

Wenn ich parent1.py mit aufrufen:

python3 parent1.py 

es gibt mir wie erwartet die folgende Ausgabe:

This text was created with child.py 

wenn ich parent2.py rufen mit:

python3 child.py | python3 parent2.py 

i die gleiche Leistung erhalten. Aber im ersten Beispiel bekomme ich die Ausgabe von child.py als Bytes und in der zweiten bekomme ich es direkt als String. Warum ist das? Ist es nur ein Unterschied zwischen Python und Bash Pipes oder gibt es etwas was ich sonst tun könnte, um dies zu vermeiden?

+0

[try this] (http://stackoverflow.com/questions/3999114/linux-pipe-into-python-ncurses-script- stdin-and-termios? answertab = Stimmen # tab-top) – scott

Antwort

3

Wenn Python stdin und stdout öffnet, erkennt es, welche Kodierung zu verwenden ist, und verwendet text I/O, um Ihnen Unicode-Strings zu geben.

Aber subprocess erkennt nicht (und kann nicht) die Codierung des von Ihnen gestarteten Subprozesses, daher gibt es Bytes zurück. Sie können ein io.TextIOWrapper() instance verwenden, um das child.stdout Rohr zu wickeln Unicode-Daten zur Verfügung zu stellen:

sys.stdin = io.TextIOWrapper(child.stdout, encoding='utf8') 
+2

Ja. Ich möchte hinzufügen, dass es im Betriebssystem nur eine Art von Pipes gibt, die von bash und Python verwendet wird. Die Interpretation eines Streams kann unterschiedlich sein, und Python unterscheidet die beiden Fälle. in einem interpretiert es die Eingabe als Bytes, in der anderen als String/Unicode. – Alfe

+0

Danke das hat funktioniert. Wenn ich jetzt etwas wie 'cat/bin/bash | parent2.py 'löst einen UnicodeDecodeError aus, weil sys.stdin.read() keine Bytes zurückgibt. Gibt es einen Weg, dies zu umgehen? – Kritzefitz

+1

@Alfe: Nun, es _interprets_ die Eingabe immer noch als Bytes in beiden Fällen, es wird nur automatisch den Stream in einem 'TextIOWrapper' für Sie im letzteren Fall. Sie können den zugrunde liegenden Byte-Stream abrufen oder in jedem Fall manuell einen eigenen Wrapper anhängen. Aber immer noch, ein nützlicher Punkt. – abarnert

Verwandte Themen