‘是’报告子进程通信错误()
- 2024-10-28 08:37:00
- admin 原创
- 52
问题描述:
我正在使用以下函数在 Python 中运行命令:
def run_proc(cmd):
child = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = child.communicate()
returncode = child.returncode
return stdout, stderr, returncode
它一直运行良好,但现在我尝试使用该yes
程序将输出传送到 stdin。我尝试运行的命令如下:
yes '' | apt-get -y -o Dpkg::Options::="--force-confdef" -o Dpkg::Options::="--force-confold" dist-upgrade
但我相信它可以用一个一般的例子来代替,例如:
yes | head -3 | cat
我的问题是,如果我尝试运行其中的任何命令yes |
,上述 subprocess.Popen 将包含错误消息:
yes: standard output: Broken pipe
yes: write error
对我来说,管道似乎仍然有效,从yes | head -3 | cat
的回答可以看出:y y y
。
我有以下问题:
即使 yes 报告错误,yes 管道是否仍然可以发挥作用?
我该如何修复它?
解决方案 1:
问题是 Python 3.2+ 之前的subprocess
模块不会将SIGPIPE
信号处理程序恢复为默认操作。这就是为什么你会得到EPIPE
写入错误。
在 Python 3.2+ 中
>>> from subprocess import check_output
>>> check_output("yes | head -3", shell=True)
b'y
y
y
'
yes
`SIGPIPE在退出时被杀死
head`。
在 Python 2 中:
>>> from subprocess import check_output
>>> check_output("yes | head -3", shell=True)
yes: standard output: Broken pipe
yes: write error
'y
y
y
'
yes
出现EPIPE
写入错误。忽略该错误是安全的。它传达的信息与 相同SIGPIPE
。
为了解决该问题,你可以restore_signals
在 Python 2 中使用preexec_fn
参数进行模拟:
>>> from subprocess import check_output
>>> import signal
>>> def restore_signals(): # from http://hg.python.org/cpython/rev/768722b2ae0a/
... signals = ('SIGPIPE', 'SIGXFZ', 'SIGXFSZ')
... for sig in signals:
... if hasattr(signal, sig):
... signal.signal(getattr(signal, sig), signal.SIG_DFL)
...
>>> check_output("yes | head -3", shell=True, preexec_fn=restore_signals)
'y
y
y
'
解决方案 2:
另一个问题回答了为什么……我会尝试给你一个解决方法
你不能做点什么吗
proc = subprocess.Popen(cmd, shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
stdin = subprocess.PIPE)
for i in range(10): #send 10 y's
time.sleep(1) # 1 second apart
proc.stdin.write("y") #you may also need to send a newline ...
print proc.communicate()
见下文(我没有考虑延迟,因为头部并没有做太多事情)
>>> import subprocess
>>> proc = subprocess.Popen("head -3",
... shell = True,
... stdout = subprocess.PIPE,
... stderr=subprocess.PIPE,
... stdin=subprocess.PIPE)
>>> for i in range(10):
... proc.stdin.write("y
")
...
>>> proc.communicate()
('y
y
y
', '')
解决方案 3:
谚语:
yes | head -3
一旦读取完 3 行输入,就会head
发送一个SIGPIPE
到,即它会发送一个信号来终止。yes
`yes`
$ yes | head -3
y
y
y
$ echo "${PIPESTATUS[@]}"
141 0
解决办法是避免SIGPIPE
!
相关推荐
热门文章
项目管理软件有哪些?
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件
热门标签
云禅道AD