2010-03-04 10 views
11

Sto usando Popen funzione dal modulo sottoprocesso per eseguire un tool a riga di comando:Qual è il subprocess.Popen lunghezza massima del parametro args?

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) 

Lo strumento che sto usando prende un elenco di file che quindi elabora. In alcuni casi, questa lista di file può essere molto lunga. C'è un modo per trovare la lunghezza massima che può essere il parametro args? Con un gran numero di file viene passato allo strumento, sto ottenendo il seguente errore:

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 

Esiste un modo generale di trovare questa lunghezza max? Ho trovato il seguente articolo su msdn: Command prompt (Cmd. exe) command-line string limitation ma non voglio inserire il codice nel valore. Preferirei ottenere il valore in fase di esecuzione per suddividere il comando in più chiamate.

Sto usando Python 2.6 su Windows XP 64.

Edit: l'aggiunta di codice di esempio

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

Il problema si verifica perché ogni ingresso effettivo nella lista paths è di solito un percorso di file molto lungo e c'è sono diverse migliaia di loro.

Non mi dispiace spezzare il comando in più chiamate a process_file.exe. Sto cercando un modo generale per ottenere la lunghezza massima che args può essere quindi so quanti percorsi inviare per ogni corsa.

+0

si potrebbe fornire un valore di esempio di ciò che si prevedono per argomenti? –

+0

Sono in ritardo per la festa ma voglio aggiungere che ho ottenuto lo stesso errore a causa della mia variabile d'ambiente PATH che diventa troppo lunga dopo l'aggiunta di molte voci. – RedX

risposta

9

Se si passa shell = False, Cmd.exe non entra in gioco.

Su Windows, il sottoprocesso utilizzerà la funzione CreateProcess dall'API Win32 per creare il nuovo processo. Il documentation per questa funzione afferma che il secondo argomento (che è compilato da subprocess.list2cmdline) ha una lunghezza massima di 32.768 caratteri, incluso il carattere null di terminazione Unicode. Se lpApplicationName è NULL, la parte del nome del modulo di lpCommandLine è limitata ai caratteri MAX_PATH.

Dato il tuo esempio, suggerisco di fornire un valore per l'eseguibile (args [0]) e l'uso di args per il primo parametro. Se la mia lettura della documentazione di CreateProcess e del codice sorgente del sottoprocesso è corretta, questo dovrebbe risolvere il tuo problema.

[edit: rimosse le args [1:] po 'dopo mettere le mani su una macchina Windows e testing]

+0

Non sono sicuro di seguire il tuo suggerimento relativo all'utilizzo di args [1:] per il primo parametro. Ho aggiornato la mia domanda con un esempio di codice. +1 per il collegamento e suggerimento su CreateProcess –

+0

Ho provato questo, ma sto ancora colpendo un limite: subprocess.Popen (cmd [1:] + percorsi, eseguibile = cmd [0], stdout = subprocesso.PIPE). Per ora sto usando 32000 come limite per la lunghezza del comando e chiamando il mio comando più volte e raccogliendo tutto l'output. Mi piacerebbe essere in grado di non avere 32000 hard coded in ma ottenere quel valore dall'ambiente. –

+0

Come menzionato nel documento I citato, il limite 32768 è codificato in modo rigido nella primitiva CreateProcess (che è il limite superiore per gli interi con segno a 16 bit, ovvero 2 ** 15). Come list2cmd aggiungerà virgolette e spazi quando costruisci la riga di comando, colpirai quel limite prima della somma ([len (a) per a in args]) raggiunge 2 ** 15. Non c'è un modo di usare i caratteri jolly per passare i tuoi argomenti all'eseguibile?(i caratteri jolly vengono generalmente elaborati dall'eseguibile sotto Windows) –

Problemi correlati