首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >shell=True的子进程不允许进程替换?

shell=True的子进程不允许进程替换?
EN

Stack Overflow用户
提问于 2016-09-30 17:47:17
回答 3查看 1K关注 0票数 0

下面是一个流程替换的玩具示例,它在Bash中运行得很好:

代码语言:javascript
运行
复制
$ wc -l <(pwd)
1 /proc/self/fd/11

那么,为什么同一个命令在使用shell=True从Python的子进程调用时会出现语法错误呢?

代码语言:javascript
运行
复制
>>> 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
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2016-09-30 17:52:15

/bin/sh: 1:语法错误:"(“意外”

你有一个巴什主义。根据POSIX,它是无效的,这是/bin/sh实现的。

票数 3
EN

Stack Overflow用户

发布于 2016-09-30 18:27:58

另一种解决方案是将更多的shell代码转移到Python本身。例如:

代码语言:javascript
运行
复制
from subprocess import Popen, PIPE, check_call

p1 = Popen(["pwd"], stdout=PIPE)
p2 = check_call(["wc", "-l"], stdin=p1.stdout)

这通常是完全消除使用subprocess的需要的第一步,因为它将工作分解成更小的块,您可以更容易地了解如何使用Python本身。

票数 2
EN

Stack Overflow用户

发布于 2021-01-04 17:42:19

如果您想使用Bash特性(数组、命令替换、这里的字符串、或许多其他非POSIX扩展和增强。),您需要显式地覆盖默认的shell:

代码语言:javascript
运行
复制
subprocess.check_call(
    'wc -l <(pwd)',
    executable='/bin/bash',  # the beef
    shell=True)

或者--有点笨拙--运行一个显式Bash实例:

代码语言:javascript
运行
复制
subprocess.check_call(
    ['/bin/bash', '-c', 'wc -l <(pwd)'])

注意,在后一种情况下,我们如何避免单独指定shell=True,并将脚本作为字符串列表传递(其中第三个字符串是一个任意复杂和/或长的脚本,作为bash -c的参数)。

(实际上有一个长度限制。如果命令行比内核常量ARG_MAX长,则需要在文件中或作为标准输入传递脚本到shell。然而,在任何现代系统中,我们谈论的都是兆字节的脚本。

无论如何,从Python运行复杂的shell脚本(Bash或其他脚本)是值得怀疑的;您将希望尽可能少地将其委托给subprocess,并在本地Python代码中使用它。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39797234

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档