我需要在我的本地主机上使用Python运行命令date | grep -o -w '"+tz+"'' | wc -w
。我使用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
6条答案
按热度按时间r55awzrz1#
必须添加
shell=True
才能执行shell命令。check_output
正在尝试查找名为的可执行文件:date | grep -o -w '"+tz+"'' | wc -w
,他找不到它。(不知道为什么你从错误消息中删除了基本信息)。查看两者之间的区别:
还有:
有关
shell
参数及其如何更改其他参数解释的详细信息,请阅读有关“常用参数”的文档。请注意,您应该尽量避免使用
shell=True
,因为生成shell可能会带来安全隐患(即使您不执行Shellshock之类的不受信任的输入攻击,也可能会被执行!)。subprocess模块的文档中有一小部分是关于替换shell管道的,你可以通过在python中派生两个进程并使用
subprocess.PIPE
来实现:您可以编写一些简单的 Package 函数来轻松定义管道:
有了它,你可以写
pipeline('date | grep 1')
或pipeline('date', 'grep 1')
或pipeline(['date'], ['grep', '1'])
nzrxty8p2#
根据我的经验,
FileNotFound
with subprocess最常见的原因是在命令中使用了空格。如果只有一个命令(不是管道,也没有重定向、通配符等),请使用列表。此更改不会导致更多的
FileNotFound
错误,如果您在此处使用更简单的命令搜索该异常,则这是一个很好的解决方案。如果需要管线或其他壳特征,简单的解决方法是添加
shell=True
:但是,如果您使用的是python 3.5或更高版本,请尝试使用以下方法:
你应该看到一个命令的输出如何变成另一个命令的输入,就像使用shell管道一样,但是你可以很容易地调试python中过程的每一步。subprocess.run对于python 3.5以上的版本,建议使用www.example.com,但在以前的版本中不可用。
oug3syen3#
FileNotFoundError
的出现是因为--在没有shell=True
的情况下-- Python试图找到一个可执行文件,它的文件名是你传入的整个字符串。你需要添加shell=True
来让shell解析和执行这个字符串,或者弄清楚如何重新表达这个命令行以避免需要shell。顺便说一句,这里的shell编程绝对是怪异的。在任何正常的系统上,
date
绝对不会输出"+tz+"
,所以剩下的处理是没有意义的。此外,使用
wc -w
来计算grep
的输出字数并不常见,更常见的用例(如果不能简单地使用grep -c
来计算匹配行数)是使用wc -l
来计算grep
的输出行数。不管怎样,如果可以的话,you want to avoid
shell=True
;如果此处的目的是测试date
命令,则可能应该用本地Python代码替换shell脚本的其余部分。优点:
date
),而不需要类似Unix的平台。缺点:
这样,如果只是想计算
"+tz+"
在date
的输出中出现的次数,请尝试关键字参数
text=True
需要Python 3.7;为了兼容早期的Python版本,可以尝试(用词不当)遗留同义词universal_newlines=True
。对于真正的旧Python版本,可以使用subprocess.check_output()
。如果你真的需要
grep
的-w
选项的语义,你需要检查与匹配项相邻的字符是否不是字母,并排除那些不是字母的字符。我将把它作为一个练习,事实上,我会假设这里原始的shell脚本实现实际上是不正确的。(也许可以试试re.split(r'(?<=^|\W)"\+tz\+"(?=\W|$)', p.stdout)
。)在更普通的情况下(单个命令、没有管道、通配符、重定向、shell内置等等),你可以使用Python的
shlex.split()
将一个命令解析成一个正确引用的参数列表。注意常规字符串
split()
在这里是完全不合适的;它只是在每个空格字符上进行拆分,不支持任何类型的引用或转义。(但还要注意,它只是从原始输入返回一个标记列表:(Even顺便说一句,这并不是原始输入,它在
'"+tz+"'
后面有一个多余的单引号)。这实际上是将
|
和grep
等作为参数传递给date
,而不是实现shell管道!您仍然需要了解您在做什么。)t5zmwmid4#
上面的问题已经有了答案,但只是以防万一解决方案对您不起作用;请检查路径本身,并检查是否为进程设置了所有环境变量以查找路径。
i86rm4rw5#
我在Python3.8.10上的工作方式(灵感来自@mightypile解决方案,网址:https://stackoverflow.com/a/49986004/12361522),被删除了参数拆分,我也必须启用shell:
这是:
而不是:
如果有人想尝试我的解决方案(至少对于v3.8.10),下面是我的解决方案:
我有至少2个文件类型(. jpg和其他)的多个文件的目录。我需要计数特定的文件类型(. jpg),而不是目录中的所有文件,通过1管道:
最后我把它弄到了这里
它不适用于拆分:
使
ls
忽略约束*.jpg
的["ls", "*.jpg"]
['wc', '-l']
,它将返回正确计数,但将返回所有3个输出,而不仅仅是一个i如果没有启用的shell
shell=True
,所有这些都将无法工作8wigbo566#
我也遇到了这个错误,对我有效的是将.sh文件的行尾设置为
Unix (LF)
,而不是Windows CRLF
。