小编典典

启动包含管道命令的子进程时找不到文件错误

python

我需要date | grep -o -w '"+tz+"'' | wc -w在本地主机上使用Python运行命令
。我使用subprocess相同的模块,并使用check_output需要捕获相同输出的方法。

但是,这使我出错:

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

阅读 219

收藏
2020-12-20

共1个答案

小编典典

您必须添加shell=True执行shell命令。check_output正在尝试查找名为:的可执行文件date | grep -o -w '"+tz+"'' | wc -w,但他找不到它。(不知道为什么您从错误消息中删除了基本信息)。

看到之间的区别:

>>> 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参数及其如何更改其他参数解释的更多信息。


请注意,您应该避免使用它,shell=True因为产生外壳会带来安全隐患(即使您不执行像Shellshock这样的不受信任的输入攻击也可以执行!)。

子流程模块的文档中有一小节介绍了如何替换Shell管道。您可以通过在python中生成两个进程并使用来做到这一点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]

您可以编写一些简单的包装函数来轻松定义管道:

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'])

2020-12-20