我正在使用子流程模块中的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)
我正在使用的工具将获取一个文件列表,然后对其进行处理。在某些情况下,此文件列表可能非常长。有没有办法找到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,但我不想在值中硬编码。我宁愿在运行时获取该值,以便将命令分解为多个调用。
我在Windows XP 64上使用Python 2.6。
编辑:添加代码示例
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
的多个调用。我正在寻找一种通用的方法来获取args的最大长度,这样我就知道每次运行要发送多少条路径。
对于类Unix平台,内核常量
ARG_MAX
是defined by POSIX.,它至少需要4096字节,尽管在现代系统上,它可能是1兆字节或更多。在许多系统中,
getconf ARG_MAX
将在shell提示符处显示其值。shell实用程序
xargs
方便地允许您分解一个长命令行。例如,如果在大目录中失败,因为文件列表扩展到长度(字节)超过
ARG_MAX
的值,您可以使用(选项
-0
是一个GNU扩展名,但实际上是唯一一种完全安全的方法,可以毫不含糊地传递可能包含换行符、引用字符等的文件名列表)也可以探索相反,将一长串参数传递给
subprocess.Popen()
和朋友,类似于。。。在大多数情况下,您可能应该避免原始的
Popen()
,并让像run()
或check_call()
这样的包装函数完成大部分工作:subprocess.run()
支持3.7+中的text=True
作为universal_newlines=True
的新名称。早于3.5的Python版本没有run
,因此您需要返回到旧的遗留函数check_output
、check_call
,或者(很少)返回到call
。如果传递的是shell=False,则Cmd.exe不起作用。
在windows上,子进程将使用Win32 API中的create process函数来创建新进程。此函数的documentation声明第二个参数(由subprocess.list2cmdline生成)的最大长度为32768个字符,包括以Unicode结尾的空字符。如果lpApplicationName为空,lpCommandLine的模块名部分将限制为最大路径字符。
根据您的示例,我建议为可执行文件(args[0])提供一个值,并将args用作第一个参数。如果我对CreateProcess文档和子流程模块源代码的阅读是正确的,那么这应该可以解决您的问题。
[编辑:在接触windows计算机并进行测试后删除了args[1:]位]
相关问题 更多 >
编程相关推荐