2010-03-04 79 views
11

我使用Popen功能从子模块执行一个命令行工具:什么是args参数的subprocess.Popen max长度?

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) 

我使用这个工具把文件,它随后进程的列表。在某些情况下,这个文件列表可能会很长。有没有办法找到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 

有没有找到这个最大长度的一般方法?我在msdn上找到了以下文章:Command prompt (Cmd. exe) command-line string limitation,但我不想在该值中进行硬编码。我宁愿在运行时获取该值,以将命令分解为多个调用。

我使用Python 2.6在Windows XP 64

编辑:添加代码示例

paths = ['file1.dat','file2.dat',...,'fileX.dat'] 
cmd = ['process_file.exe','+p'] + paths 
cmd_output = subprocess.Popen(cmd,stdout=subprocess.PIPE).communicate(0)[0] 

出现问题的原因在paths列表中的每个实际入口通常是一个非常长的文件路径和有有几千人。

我不介意将命令分解为多次调用process_file.exe。我正在寻找一种通用的方法来获取参数的最大长度,所以我知道每次运行需要发送多少路径。

+0

你能提供的您提供什么ARGS一个例子价值? – 2010-03-04 17:56:41

+0

我很晚参加派对,但我想补充说,由于我的PATH环境变量在添加很多条目后变得太长,我得到了同样的错误。 – RedX 2015-12-21 12:58:08

回答

9

如果你传递的是shell = False,那么Cmd.exe不起作用。

在windows上,子进程将使用Win32 API中的CreateProcess函数来创建新进程。该函数的documentation指出第二个参数(由subprocess.list2cmdline构建)的最大长度为32,768个字符,其中包括Unicode终止空字符。如果lpApplicationName为NULL,则lpCommandLine的模块名称部分被限制为MAX_PATH个字符。

给出你的例子,我建议为可执行文件(args [0])提供一个值,并使用args作为第一个参数。如果我阅读了CreateProcess文档和子流程模块源代码是正确的,这应该可以解决您的问题。

[编辑:删除ARGS [1:]得到我的手在Windows机器和测试后位]

+0

我不确定我是否遵循了关于使用参数[1:]作为第一个参数的建议。我用代码示例更新了我的问题。 +1的链接和提示CreateProcess – 2010-03-04 18:55:21

+0

我试过这个,但我仍然触及一个限制:subprocess.Popen(cmd [1:] + path,executable = cmd [0],stdout = subprocess.PIPE)。现在我使用32000作为命令长度的限制,并多次调用我的命令并收集所有输出。我希望能够没有32000硬编码,但从环境中获得该价值。 – 2010-03-04 20:09:49

+0

就像我在文档中提到的那样,32768的限制是在CreateProcess原语中硬编码的(即16位有符号整数的上限,即2 ** 15)。由于list2cmd将在构建命令行时添加引号和空格,因此在sum([len(a)for a args])达到2 ** 15之前,您将达到该限制。没有使用通配符将参数传递给可执行文件的方法吗?(通配符通常由windows下的可执行文件处理) – 2010-03-05 08:11:32

相关问题