2013-05-08 21 views
5

I持って、次の3つのPythonスクリプト:はbashとPythonのパイプの間の差

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

私はparent1.pyを次のように呼び出します。

python3 parent1.py 

それは期待以下の出力のように私を与える:

This text was created with child.py 

私はparent2.pyを呼び出す場合:

python3 child.py | python3 parent2.py 

私は同じ出力を得ます。しかし、最初の例では、私はバイトとしてchild.pyの出力を取得し、次に文字列として直接取得します。どうしてこれなの?それは単にpythonとbashパイプの違いか、これを避けるために何かできることがありますか?

+0

(http://stackoverflow.com/questions/3999114/linux-pipe-in​​to-python-ncurses-script- [これを試してください] stdin-and-termios?answertab = votes#tab-top) – scott

答えて

3

pythonがstdinstdoutを開くと、使用するエンコードを検出し、text I/Oを使用してユニコード文字列を取得します。

しかし、subprocessは、開始するサブプロセスのエンコーディングを検出しないため、バイトを返します。あなたは、Unicodeデータを提供するために、child.stdoutパイプをラップするio.TextIOWrapper() instanceを使用することができます。

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

うん。私は、OSには1種類のパイプしか存在しないことを付け加えたいと思います。これはbashとPythonで同じものが使用されています。ストリームの解釈は異なる可能性があり、Pythonは2つのケースを区別します。一方では入力をバイトとして解釈し、もう一方では文字列/ユニコードとして解釈します。 – Alfe

+0

ありがとうございました。私は今、 'cat/bin/bash | parent2.py 'sys.stdin.read()がバイトを返さないため、UnicodeDecodeErrorが発生します。これを回避する方法はありますか? – Kritzefitz

+1

@Alfe:どちらの場合でも、入力はバイトとして入力されていますが、後者の場合は 'TextIOWrapper'でストリームを自動的にラップします。どちらの場合でも、基礎となるバイトストリームを取得したり、独自のラッパーを手動でアタッチすることができます。しかし、まだ、有用な点です。 – abarnert

関連する問題