[pyar] Lidiando con el límite de file descriptors abiertos y subprocess

QliX=D! [aka EHB] qlixed en gmail.com
Mar Ago 23 11:05:51 ART 2011


2011/8/23 Andrés Gattinoni <andresgattinoni en gmail.com>
>
> Hola listeros,
>
> El otro día mandé un mail pero con el problemita de USLA quizás se
> perdió en la estratósfera (además de que primero pregunté una cosa,
> después lo resolví y cambié mi pregunta).
> Así que vuelvo a plantear mi problema más claramente a ver si alguien
> me puede ayudar a resolver esto.
>
> Tengo este script:
> http://pastebin.com/zsbzLABn
>
> Es un hook para el SVN para el evento pre-commit, que toma todos los
> scripts de PHP, JS y BASH que hayan sido modificados y corre un
> chequeo de sintaxis para evitar comitear archivos con ese tipo de
> errores. El script funciona bien en general, pero cuando tiene que
> chequear una gran cantidad de archivos da problemas.
>
> Concretamente el error que me está dando ahora es este:
>
> Traceback (most recent call last):
>  File "/home/subversion/svn_test/hooks/pre-commit", line 188, in <module>
>    sys.exit(main(sys.argv))
>  File "/home/subversion/svn_test/hooks/pre-commit", line 184, in main
>    return check_commit(rep, txn)
>  File "/home/subversion/svn_test/hooks/pre-commit", line 169, in check_commit
>    errors += check_file(f, checkers, rep, txn)
>  File "/home/subversion/svn_test/hooks/pre-commit", line 148, in check_file
>    r = check(tmpfile, filename)
>  File "/home/subversion/svn_test/hooks/pre-commit", line 85, in check_php
>    return run([_PHP_PATH, '-l', filename], filename, realname)
>  File "/home/subversion/svn_test/hooks/pre-commit", line 67, in run
>    stderr=subprocess.PIPE)
>  File "/usr/lib/python2.6/subprocess.py", line 633, in __init__
>    errread, errwrite)
>  File "/usr/lib/python2.6/subprocess.py", line 1039, in _execute_child
>    errpipe_read, errpipe_write = os.pipe()
> OSError: [Errno 24] Too many open files

Yo tocaria el popen asi:
p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT, close_fds=True)

Si estas en windows no uses close_fds.
Con eso Juntas stdout y stderr con lo que reducis a la mitad los pipe usados.
La otra que te queda es usar un archivo unico para las salidas:

f= subprocess.Popen(cmd, stdout=fileobject,  stderr=subprocess.STDOUT,
close_fds=True)

Entonces todas las salidas te quedan en el fileobject.

Otra idea, un poco mas piola me parece, es hacer una ejecucion doble
en caso de error, como es esto?:
1. Ejecutas un popen con stdout=None, stderr=None.
2. Analizas el p.returncode
  2.1. Si dio error entonces ejecutas un popen con los pipes o el fileobject.
  2.2. Obtenes el stdout y lo mostras (o acumulas para mostrar dps).

Esto hace dos ejecuciones de popen, pero solo en caso de que el
archivo contenga errores.
Con eso creo que minimizas al maximo los FDs.

Saludos
QliXed



More information about the pyar mailing list