Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python:subprocess.call断开的管道_Python_Bash_Subprocess - Fatal编程技术网

Python:subprocess.call断开的管道

Python:subprocess.call断开的管道,python,bash,subprocess,Python,Bash,Subprocess,我试图用python调用一个shell脚本,但它一直报告断管错误(结果是可以的,但我不想在STDERR中看到错误消息)。我已经查明了原因,可以复制为以下片段: subprocess.call('cat/dev/zero | head-c10 | base64',shell=True) AAAAAAAAAAAAAA== cat:写入错误:管道断裂 /dev/zero是一个无限流,但是头-c10只从中读取10个字节并退出,然后cat将获得SIGPIPE,因为对等方已关闭管道。当我在shell中运行命

我试图用python调用一个shell脚本,但它一直报告断管错误(结果是可以的,但我不想在STDERR中看到错误消息)。我已经查明了原因,可以复制为以下片段:

subprocess.call('cat/dev/zero | head-c10 | base64',shell=True)

AAAAAAAAAAAAAA==

cat:写入错误:管道断裂


/dev/zero
是一个无限流,但是
头-c10
只从中读取10个字节并退出,然后cat将获得SIGPIPE,因为对等方已关闭管道。当我在shell中运行命令时,没有出现断管错误消息,但是为什么python会显示它呢?

在这个简单的例子中,至少使用shell命令没有获得任何好处,并且失去了可移植性和速度

Python 2代码:

>>> import base64
>>> base64.b64encode(open('/dev/zero', 'rb').read(10))
'AAAAAAAAAAAAAA=='
>>> base64.b64encode('\0' * 10)
'AAAAAAAAAAAAAA=='
在Python 3中(代码也将在2.6+中运行,尽管它将返回
str
而不是
bytes
实例):


在每种情况下,第一个示例都保留了
/dev/zero
(本身不可移植,但没关系),第二个示例产生了效果,尽管我想这不是您特别想要的?

SIGPIPE信号的默认操作是终止程序。Python解释器将其更改为SIG_IGN,以便能够以异常的形式向程序报告中断的管道错误

当您执行
cat时|head…
在shell中,
cat
有默认的SIGPIPE处理程序,操作系统内核只是在SIGPIPE上终止它

当您使用
subprocess
执行
cat
时,它从其父级(python解释器)派生出SIGPIPE处理程序,SIGPIPE被忽略,
cat
通过检查
errno
变量并打印错误消息来处理错误本身

要避免来自
cat
的错误消息,可以使用
preexec\u fn
参数来调用subprocess.call:

from signal import signal, SIGPIPE, SIG_DFL
subprocess.call(
    'cat /dev/zero | head -c 10 | base64',
    shell = True,
    preexec_fn = lambda: signal(SIGPIPE, SIG_DFL)
)

当您跳过:
subprocess.call('head-c10
@larsmans:您可以将其作为answer@ChrisMorgan:事实上,我更喜欢你的答案。@larsmans:这取决于他在做什么。如果不仅仅是像
head
base64
这样简单的事情,那么在纯Python中管理它可能太困难了。您的问题解决了所问的问题,这是有价值的。@ChrisMorgan:true。不过,如果我明白发生了什么,我只会发布一个答案,而我不知道。我以前从未见过猫抱怨管道破裂,总是依赖它在管道关闭时默默退出。+1<代码>'\x00'
也可以用Python 3.x编写
'\0'
(或
b'\0'
)。我想我更喜欢subdir的答案,它直接解决了问题,并解释了问题。非常好,非常感谢,刚刚用cat的shell脚本解决了我的问题(我相当肯定它不是UOOC,也许这是另一个问题!)非常好!修复了使用subprocess.call()调用bash脚本导致的tr:breaked管道错误
from signal import signal, SIGPIPE, SIG_DFL
subprocess.call(
    'cat /dev/zero | head -c 10 | base64',
    shell = True,
    preexec_fn = lambda: signal(SIGPIPE, SIG_DFL)
)