【发布时间】:2015-06-30 08:54:40
【问题描述】:
我在 Linux 3.16.0 上运行 Python 3.4.3。我想使用subprocess.Popen 运行一个带有长单个参数(复杂的 Bash 调用)的命令,大约 200KiB。
根据getconf 和xargs,这应该在我的范围内:
$ getconf ARG_MAX
2097152
$ xargs --show-limits < /dev/null
Your environment variables take up 3364 bytes
POSIX upper limit on argument length (this system): 2091740
POSIX smallest allowable upper limit on argument length (all systems): 4096
Maximum length of command we could actually use: 2088376
Size of command buffer we are actually using: 131072
但是,Python 失败的限制要小得多:
>>> subprocess.Popen('echo %s > /dev/null' % ('a' * (131072-4096)), shell=True, executable='/bin/bash')
<subprocess.Popen object at 0x7f4613b58410>
>>> subprocess.Popen('echo %s > /dev/null' % ('a' * (262144-4096)), shell=True, executable='/bin/bash')
Traceback (most recent call last):
[...]
OSError: [Errno 7] Argument list too long
请注意,Python 限制与“实际使用”命令缓冲区 xargs 报告的大致相同。这表明xargs 在某种程度上足够聪明,可以从较小的限制开始并根据需要增加限制,但 Python 不是。
问题:
- 为什么 Python 限制小于 2MiB 的 OS 限制?
- 我可以增加 Python 限制吗?
- 如果是,怎么做?
【问题讨论】:
-
不要使用
subprocess.Popen()的“单字符串”API。总是传递一个列表。避免shell=True。 -
在这种情况下,我实际上是在子进程中依赖 Bash 功能。
-
试试
subprocess.Popen('echo $SHELL')。我认为这会给你/bin/sh,而不是 bash。 -
仅仅因为 ARGMAX 显示 2097152 并不意味着,尝试
131071和131072 -
您需要进入管道或临时文件,适当刷新,避免死锁,处理流输出(
communicate()不适合我的用例)等等。无论如何,这行讨论是这个问题的话题。请用它来聊天或打开您自己的问题。
标签: python linux python-3.x subprocess command-line-arguments