bash和python管道之间的区别

bash和python管道之间的区别,python,bash,python-3.x,pipe,python-3.2,Python,Bash,Python 3.x,Pipe,Python 3.2,我有以下三个python脚本: 家长1.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.

我有以下三个python脚本:

家长1.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管道之间的区别,还是我可以做些其他的事情来避免这种情况?

当python打开
stdin
stdout
时,它会检测要使用的编码并使用它来为您提供unicode字符串

但是
子进程
没有(也不能)检测到您启动的子进程的编码,因此它将返回字节。您可以使用包装子.stdout管道来提供unicode数据:

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

是的。我想补充一点,操作系统中只有一种管道,bash和Python都使用这种管道。流的解释可能不同,Python区分了这两种情况;其中一个将输入解释为字节,另一个将输入解释为字符串/unicode。谢谢你的帮助。如果我现在想执行类似于“cat/bin/bash | parent2.py”的操作,它会引发UnicodeDecodeError,因为sys.stdin.read()不返回字节。有办法解决这个问题吗?@Alfe:嗯,在这两种情况下,它仍然将输入解释为字节,在后一种情况下,它只是自动将流包装成
TextIOWrapper
。在这两种情况下,您都可以获取底层字节流,或者手动附加自己的包装器。但还是有一点很有用。@IchUndNichtDu:
sys.stdin
和其他东西一样,只是一个常规的
TextIOWrapper
。(试着打印它的
repr
),这样,你就可以用所有常用的方法获取其中的字节。例如,您可以从中获取其
fileno()
os.read()
(但不要混淆从包装器和fileno中读取的内容!)。@IchUndNichtDu:您可以尝试查看对象是否具有
encoding
属性;如果没有,你需要包装它
if not hasattr(fileobj,'encoding'):fileobj=io.TextIOWrapper(fileobj,encoding=…)