启动包含管道命令的子进程时找不到文件错误 [英] File not found error when launching a subprocess containing piped commands

查看:17
本文介绍了启动包含管道命令的子进程时找不到文件错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

但是它给我一个错误:

回溯(最近一次调用最后一次):文件test.py",第 47 行,在 <module> 中check_timezone()文件test.py",第 40 行,在 check_timezone计数 = subprocess.check_output(命令)文件/usr/lib/python2.7/subprocess.py",第 537 行,在 check_output 中进程 = Popen(stdout=PIPE, *popenargs, **kwargs)文件/usr/lib/python2.7/subprocess.py",第 679 行,在 __init__ 中错误读取,错误写入)文件/usr/lib/python2.7/subprocess.py",第 1249 行,在 _execute_child 中提出 child_exception-OSError: [Errno 2] 没有那个文件或目录

解决方案

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

查看两者的区别:

<预><代码>>>>subprocess.check_output('date | grep 1')回溯(最近一次调用最后一次):文件<stdin>",第 1 行,在 <module> 中文件/usr/lib/python3.4/subprocess.py",第 603 行,在 check_output 中使用 Popen(*popenargs, stdout=PIPE, **kwargs) 作为进程:文件/usr/lib/python3.4/subprocess.py",第 848 行,在 __init__ 中restore_signals,start_new_session)文件/usr/lib/python3.4/subprocess.py",第 1446 行,在 _execute_child 中引发 child_exception_type(errno_num, err_msg)FileNotFoundError: [Errno 2] 没有这样的文件或目录:'date |格雷普 1'

还有:

<预><代码>>>>subprocess.check_output('date | grep 1', shell=True)b'gio 19 giu 2014, 14.15.35, CEST '

阅读有关常用参数的文档以了解更多信息关于 shell 参数的信息以及它如何改变其他参数的解释.

<小时>

请注意,您应该尽量避免使用 shell=True,因为生成 shell 可能存在安全隐患(即使您不执行像 Shellshock 这样的不受信任的输入攻击,仍然可以执行!).

subprocess 模块的文档有一小部分是关于更换外壳管道.您可以通过在 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()输出 = grep_proc.communicate()[0]

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

导入子流程从 shlex 导入拆分从集合导入namedtuple从 functools 导入减少proc_output = namedtuple('proc_output', 'stdout stderr')定义管道(starter_command,*commands):如果不是命令:尝试:starter_command, *commands = starter_command.split('|')除了属性错误:经过starter_command = _parse(starter_command)starter = subprocess.Popen(starter_command, stdout=subprocess.PIPE)last_proc = reduce(_create_pipe, map(_parse, commands), starter)返回 proc_output(*last_proc.communicate())def _create_pipe(上一个,命令):proc = subprocess.Popen(command, stdin=previous.stdout, stdout=subprocess.PIPE)以前的.stdout.close()退货流程def_parse(cmd):尝试:返回拆分(cmd)除了例外:返回命令

有了这个,你可以编写 pipeline('date | grep 1')pipeline('date', 'grep 1')pipeline(['date'], ['grep', '1'])

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

解决方案

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).

See the difference between:

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

And:

>>> subprocess.check_output('date | grep 1', shell=True)
b'gio 19 giu 2014, 14.15.35, CEST
'

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.


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!).

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

With this in place you can write pipeline('date | grep 1') or pipeline('date', 'grep 1') or pipeline(['date'], ['grep', '1'])

这篇关于启动包含管道命令的子进程时找不到文件错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆