下面是一个流程替换的玩具示例,它在Bash中运行得很好:
$ wc -l <(pwd)
1 /proc/self/fd/11那么,为什么同一个命令在使用shell=True从Python的子进程调用时会出现语法错误呢?
>>> subprocess.check_call('wc -l <(pwd)', shell=True)
/bin/sh: 1: Syntax error: "(" unexpected
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/path/to/my/python/lib/python3.5/subprocess.py", line 581, in check_call
    raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command 'wc -l <(pwd)' returned non-zero exit status 2发布于 2016-09-30 17:52:15
/bin/sh: 1:语法错误:"(“意外”
你有一个巴什主义。根据POSIX,它是无效的,这是/bin/sh实现的。
发布于 2016-09-30 18:27:58
另一种解决方案是将更多的shell代码转移到Python本身。例如:
from subprocess import Popen, PIPE, check_call
p1 = Popen(["pwd"], stdout=PIPE)
p2 = check_call(["wc", "-l"], stdin=p1.stdout)这通常是完全消除使用subprocess的需要的第一步,因为它将工作分解成更小的块,您可以更容易地了解如何使用Python本身。
发布于 2021-01-04 17:42:19
如果您想使用Bash特性(数组、命令替换、这里的字符串、或许多其他非POSIX扩展和增强。),您需要显式地覆盖默认的shell:
subprocess.check_call(
    'wc -l <(pwd)',
    executable='/bin/bash',  # the beef
    shell=True)或者--有点笨拙--运行一个显式Bash实例:
subprocess.check_call(
    ['/bin/bash', '-c', 'wc -l <(pwd)'])注意,在后一种情况下,我们如何避免单独指定shell=True,并将脚本作为字符串列表传递(其中第三个字符串是一个任意复杂和/或长的脚本,作为bash -c的参数)。
(实际上有一个长度限制。如果命令行比内核常量ARG_MAX长,则需要在文件中或作为标准输入传递脚本到shell。然而,在任何现代系统中,我们谈论的都是兆字节的脚本。
无论如何,从Python运行复杂的shell脚本(Bash或其他脚本)是值得怀疑的;您将希望尽可能少地将其委托给subprocess,并在本地Python代码中使用它。
https://stackoverflow.com/questions/39797234
复制相似问题