2013-05-08 36 views
5

Tôi có ba kịch bản python sau:Sự khác biệt giữa bash và trăn Ống

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

Nếu tôi gọi parent1.py bằng:

python3 parent1.py 

nó mang lại cho tôi như dự kiến ​​đầu ra sau đây:

This text was created with child.py 

nếu tôi gọi parent2.py với:

python3 child.py | python3 parent2.py 

tôi nhận được đầu ra tương tự. Nhưng trong ví dụ đầu tiên tôi nhận được kết quả đầu ra của child.py dưới dạng byte và trong phần thứ hai tôi lấy nó trực tiếp dưới dạng một chuỗi. Tại sao điều này? Nó chỉ là một sự khác biệt giữa python và bash ống hoặc là có một cái gì đó tôi có thể làm khác để tránh điều này?

+0

[thử này] (http://stackoverflow.com/questions/3999114/linux-pipe-into-python-ncurses-script- stdin-and-termios? answerertab = phiếu # tab-top) – scott

Trả lời

3

Khi python mở stdinstdout, nó sẽ phát hiện mã hóa nào sẽ sử dụng và sử dụng text I/O để cung cấp cho bạn chuỗi unicode.

Nhưng subprocess không (và không thể) phát hiện mã hóa của quy trình con bạn bắt đầu, vì vậy nó sẽ trả về byte. Bạn có thể sử dụng một io.TextIOWrapper() instance để quấn child.stdout ống để cung cấp dữ liệu unicode:

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

Đúng. Tôi muốn thêm rằng chỉ có một loại đường ống trong hệ điều hành và được sử dụng bởi bash và Python chỉ giống nhau. Việc giải thích một luồng có thể khác nhau và Python phân biệt hai trường hợp; trong một nó diễn giải đầu vào là byte, còn lại là chuỗi/unicode. – Alfe

+0

Cảm ơn bạn đã làm việc. Nếu bây giờ tôi muốn làm một cái gì đó như 'cat/bin/bash | parent2.py 'nó làm tăng UnicodeDecodeError vì sys.stdin.read() không trả về byte. Có cách nào để giải quyết vấn đề này không? – Kritzefitz

+1

@Alfe: Vâng, nó vẫn _interprets_ đầu vào là byte trong cả hai trường hợp, nó chỉ tự động kết thúc tốt đẹp luồng trong một 'TextIOWrapper' cho bạn trong trường hợp sau. Bạn có thể nhận được ở dòng byte cơ bản, hoặc tự đính kèm trình bao bọc của riêng bạn, trong cả hai trường hợp. Nhưng vẫn còn, một điểm hữu ích. – abarnert

Các vấn đề liên quan