python args 参数的 subprocess.Popen 最大长度是多少?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2381241/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is the subprocess.Popen max length of the args parameter?
提问by Jesse Vogt
I am using Popenfunction from the subprocess module to execute a command line tool:
我正在使用subprocess模块中的Popen函数来执行命令行工具:
subprocess.Popen(args, bufsize=0, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=False, shell=False, cwd=None, env=None, universal_newlines=False, startupinfo=None, creationflags=0)
The tool I am using takes a list of files that it then processes. In some cases, this list of files can be very long. Is there a way to find the max length that the args parameter can be? With a large number of files being passed to the tool, I am getting the following error:
我正在使用的工具需要一个文件列表,然后它会处理这些文件。在某些情况下,此文件列表可能很长。有没有办法找到 args 参数的最大长度?将大量文件传递给该工具后,出现以下错误:
Traceback (most recent call last):
File "dump_output_sopuids.py", line 68, in <module>
uid_map = create_sopuid_to_path_dict_dcmdump(dicom_files)
File "dump_output_sopuids.py", line 41, in create_sopuid_to_path_dict_dcmdump
dcmdump_output = subprocess.Popen(cmd,stdout=subprocess.PIPE).communicate(0)[0]
File "c:\python26\lib\subprocess.py", line 621, in __init__
errread, errwrite)
File "c:\python26\lib\subprocess.py", line 830, in _execute_child
startupinfo)
WindowsError: [Error 206] The filename or extension is too long
Is there a general way to find this max length? I found the following article on msdn: Command prompt (Cmd. exe) command-line string limitationbut I don't want to hard code in the value. I would rather get the value at run time to break up the command into multiple calls.
有没有通用的方法来找到这个最大长度?我在 msdn 上找到了以下文章:命令提示符(Cmd.exe)命令行字符串限制,但我不想在值中进行硬编码。我宁愿在运行时获取该值以将命令分解为多个调用。
I am using Python 2.6 on Windows XP 64.
我在 Windows XP 64 上使用 Python 2.6。
Edit: adding code example
编辑:添加代码示例
paths = ['file1.dat','file2.dat',...,'fileX.dat']
cmd = ['process_file.exe','+p'] + paths
cmd_output = subprocess.Popen(cmd,stdout=subprocess.PIPE).communicate(0)[0]
The problem occurs because each actual entry in the paths
list is usually a very long file path AND there are several thousand of them.
出现问题是因为paths
列表中的每个实际条目通常是一个很长的文件路径,并且有数千个。
I don't mind breaking up the command into multiple calls to process_file.exe
. I am looking for a general way to get the max length that args can be so I know how many paths to send in for each run.
我不介意将命令分解为对process_file.exe
. 我正在寻找一种通用方法来获得 args 的最大长度,以便我知道每次运行要发送多少条路径。
采纳答案by gurney alex
If you're passing shell=False, then Cmd.exe does not come into play.
如果您传递 shell=False,则 Cmd.exe 不会起作用。
On windows, subprocess will use the CreateProcess function from Win32 API to create the new process. The documentationfor this function states that the second argument (which is build by subprocess.list2cmdline) has a max length of 32,768 characters, including the Unicode terminating null character. If lpApplicationName is NULL, the module name portion of lpCommandLine is limited to MAX_PATH characters.
在 Windows 上,子进程将使用 Win32 API 中的 CreateProcess 函数来创建新进程。此函数的文档说明第二个参数(由 subprocess.list2cmdline 构建)的最大长度为 32,768 个字符,包括 Unicode 终止空字符。如果 lpApplicationName 为 NULL,则 lpCommandLine 的模块名称部分被限制为 MAX_PATH 个字符。
Given your example, I suggest providing a value for executable (args[0]) and using args for the first parameter. If my reading of the CreateProcess documentation and of the subprocess module source code is correct, this should solve your problem.
鉴于您的示例,我建议为可执行文件 (args[0]) 提供一个值并使用 args 作为第一个参数。如果我对 CreateProcess 文档和 subprocess 模块源代码的阅读是正确的,这应该可以解决您的问题。
[edit: removed the args[1:] bit after getting my hands on a windows machine and testing]
[编辑:在我拿到 Windows 机器并测试后删除了 args[1:] 位]
回答by tripleee
For Unix-like platforms, the kernel constant ARG_MAX
is defined by POSIX.It is required to be at least 4096 bytes, though on modern systems, it's probably a megabyte or more.
对于类Unix平台,内核常数ARG_MAX
是通过POSIX定义。它至少需要 4096 字节,但在现代系统上,它可能是 1 兆字节或更多。
On many systems, getconf ARG_MAX
will reveal its value at the shell prompt.
在许多系统上,getconf ARG_MAX
会在 shell 提示下显示它的值。
The shell utility xargs
conveniently allows you to break up a long command line. For example, if
shell 实用程序可以xargs
方便地拆分长命令行。例如,如果
python myscript.py *
fails in a large directory because the list of files expands to a value whose length in bytes exceeds ARG_MAX
, you can work around it with something like
在大目录中失败,因为文件列表扩展到一个字节长度超过的值ARG_MAX
,您可以使用类似的方法解决它
printf '%sfind . -maxdepth 1 -type f -exec python myscript.py {} +
' * |
xargs -0 python myscript.py
(The option -0
is a GNU extension, but really the only completely safe way to unambiguously pass a list of file names which could contain newlines, quoting characters, etc.) Maybe also explore
(该选项-0
是 GNU 扩展,但实际上是唯一完全安全的方式来明确传递可能包含换行符、引用字符等的文件名列表。)也许还可以探索
p = subprocess.Popen(['xargs', '-0', 'command'],
stdin=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
out, err = p.communicate('r = subprocess.run(['xargs', '-0', 'command'],
input='##代码##'.join(long_long_argument_list),
universal_newlines=True)
out = r.stdout
'.join(long_long_argument_list))
Conversely, to pass a long list of arguments to subprocess.Popen()
and friends, something like
相反,要将一长串参数传递给subprocess.Popen()
和朋友,例如
... where in most scenarios you should probably avoid raw Popen()
and let a wrapper function like run()
or check_call()
do most of the work:
...在大多数情况下,您应该避免使用 rawPopen()
并让包装函数像run()
或check_call()
完成大部分工作:
subprocess.run()
supports text=True
in 3.7+ as the new name of universal_newlines=True
. Older Python versions than 3.5 didn't have run
, so you need to fall back to the older legacy functions check_output
, check_call
, or (rarely) call
.
subprocess.run()
支持text=True
3.7+ 作为universal_newlines=True
. 较早的Python版本比3.5没有run
,所以你需要退回到旧的传统功能check_output
,check_call
或(很少)call
。