启动包含管道命令的子进程时,找不到文件错误 [英] File not found error when launching a subprocess containing piped commands
问题描述
我需要在本地主机上使用Python运行命令date | grep -o -w '"+tz+"'' | wc -w
.我正在使用subprocess
模块,并使用check_output
方法,因为我需要捕获同一模块的输出.
I need to run the command date | grep -o -w '"+tz+"'' | wc -w
using Python on my localhost. I am using subprocess
module for the same and using the check_output
method as I need to capture the output for the same.
但是它给我抛出了一个错误:
However it is throwing me an error :
Traceback (most recent call last):
File "test.py", line 47, in <module>
check_timezone()
File "test.py", line 40, in check_timezone
count = subprocess.check_output(command)
File "/usr/lib/python2.7/subprocess.py", line 537, in check_output
process = Popen(stdout=PIPE, *popenargs, **kwargs)
File "/usr/lib/python2.7/subprocess.py", line 679, in __init__
errread, errwrite)
File "/usr/lib/python2.7/subprocess.py", line 1249, in _execute_child
raise child_exception-
OSError: [Errno 2] No such file or directory
推荐答案
您必须添加shell=True
才能执行Shell命令. check_output
试图找到一个名为:date | grep -o -w '"+tz+"'' | wc -w
的可执行文件,但他找不到它. (不知道为什么您从错误消息中删除了基本信息).
You have to add shell=True
to execute a shell command. check_output
is trying to find an executable called: date | grep -o -w '"+tz+"'' | wc -w
and he cannot find it. (no idea why you removed the essential information from the error message).
查看两者之间的区别:
>>> subprocess.check_output('date | grep 1')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python3.4/subprocess.py", line 603, in check_output
with Popen(*popenargs, stdout=PIPE, **kwargs) as process:
File "/usr/lib/python3.4/subprocess.py", line 848, in __init__
restore_signals, start_new_session)
File "/usr/lib/python3.4/subprocess.py", line 1446, in _execute_child
raise child_exception_type(errno_num, err_msg)
FileNotFoundError: [Errno 2] No such file or directory: 'date | grep 1'
并且:
>>> subprocess.check_output('date | grep 1', shell=True)
b'gio 19 giu 2014, 14.15.35, CEST\n'
阅读有关常用参数的文档,以了解更多信息shell
自变量及其如何更改其他自变量的解释的信息.
Read the documentation about the Frequently Used Arguments for more information about the shell
argument and how it changes the interpretation of the other arguments.
请注意,您应尽量避免使用shell=True
,因为产生外壳可能会带来安全隐患(即使您不执行像Shellshock这样的不受信任的输入攻击也可以执行!).
Note that you should try to avoid using shell=True
since spawning a shell can be a security hazard (even if you do not execute untrusted input attacks like Shellshock can still be performed!).
子流程模块的文档中有一小节关于替换外壳管道.
您可以通过在python中生成两个进程并使用subprocess.PIPE
:
The documentation for the subprocess module has a little section about replacing the shell pipeline.
You can do so by spawning the two processes in python and use subprocess.PIPE
:
date_proc = subprocess.Popen(['date'], stdout=subprocess.PIPE)
grep_proc = subprocess.check_output(['grep', '1'], stdin=date_proc.stdout, stdout=subprocess.PIPE)
date_proc.stdout.close()
output = grep_proc.communicate()[0]
您可以编写一些简单的包装函数来轻松定义管道:
You can write some simple wrapper function to easily define pipelines:
import subprocess
from shlex import split
from collections import namedtuple
from functools import reduce
proc_output = namedtuple('proc_output', 'stdout stderr')
def pipeline(starter_command, *commands):
if not commands:
try:
starter_command, *commands = starter_command.split('|')
except AttributeError:
pass
starter_command = _parse(starter_command)
starter = subprocess.Popen(starter_command, stdout=subprocess.PIPE)
last_proc = reduce(_create_pipe, map(_parse, commands), starter)
return proc_output(*last_proc.communicate())
def _create_pipe(previous, command):
proc = subprocess.Popen(command, stdin=previous.stdout, stdout=subprocess.PIPE)
previous.stdout.close()
return proc
def _parse(cmd):
try:
return split(cmd)
except Exception:
return cmd
在此位置,您可以编写pipeline('date | grep 1')
或pipeline('date', 'grep 1')
或pipeline(['date'], ['grep', '1'])
With this in place you can write pipeline('date | grep 1')
or pipeline('date', 'grep 1')
or pipeline(['date'], ['grep', '1'])
这篇关于启动包含管道命令的子进程时,找不到文件错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!