¿Por qué el límite de longitud del argumento subprocess.Popen es más pequeño que lo que informa el sistema operativo?

Estoy ejecutando Python 3.4.3 en Linux 3.16.0. Quiero usar subprocess.Popen para ejecutar un comando con un solo argumento largo (una invocación compleja de Bash), aproximadamente 200 KB.

Según getconf y xargs , esto debería estar dentro de mis límites:

 $ getconf ARG_MAX 2097152 $ xargs --show-limits < /dev/null Your environment variables take up 3364 bytes POSIX upper limit on argument length (this system): 2091740 POSIX smallest allowable upper limit on argument length (all systems): 4096 Maximum length of command we could actually use: 2088376 Size of command buffer we are actually using: 131072 

Sin embargo, Python falla con límites bastante más pequeños:

 >>> subprocess.Popen('echo %s > /dev/null' % ('a' * (131072-4096)), shell=True, executable='/bin/bash')  >>> subprocess.Popen('echo %s > /dev/null' % ('a' * (262144-4096)), shell=True, executable='/bin/bash') Traceback (most recent call last): [...] OSError: [Errno 7] Argument list too long 

Tenga en cuenta que el límite de Python es aproximadamente el mismo que el de los informes de xargs búfer de comandos “en realidad usando”. Esto sugiere que xargs es de alguna manera lo suficientemente inteligente como para comenzar con un límite más pequeño y boostlo según sea necesario, pero Python no lo es.

Preguntas:

  1. ¿Por qué el límite de Python es más pequeño que el límite del sistema operativo de 2MiB?
  2. ¿Puedo boost el límite de Python?
  3. ¿Si es así, cómo?

El tamaño máximo para un solo argumento de cadena está limitado a 131072. No tiene nada que ver con python:

 ~$ /bin/echo "$(printf "%*s" 131071 "a")">/dev/null ~$ /bin/echo "$(printf "%*s" 131072 "a")">/dev/null bash: /bin/echo: Argument list too long 

En realidad, es MAX_ARG_STRLEN que decide el tamaño máximo para una sola cadena:

Y como límite adicional desde 2.6.23, un argumento no debe ser más largo que MAX_ARG_STRLEN (131072). Esto puede ser relevante si genera una llamada larga como “sh -c ‘generada con argumentos largos'”. (señalado por Xan Lopez y Ralf Wildenhues)

Consulte esta discusión de ARG_MAX , bajo “Número de argumentos y longitud máxima de un argumento”, y esta pregunta en unix.stackexchange .

Puedes verlo en binfmts.h :

 /* * These are the maximum length and maximum number of strings passed to the * execve() system call. MAX_ARG_STRLEN is essentially random but serves to * prevent the kernel from being unduly impacted by misaddressed pointers. * MAX_ARG_STRINGS is chosen to fit in a signed 32-bit integer. */ #define MAX_ARG_STRLEN (PAGE_SIZE * 32) #define MAX_ARG_STRINGS 0x7FFFFFFF ~$ echo $(( $(getconf PAGE_SIZE)*32 )) 131072 

Puede pasar varias cadenas de longitud 131071 :

 subprocess.check_call(['echo', "a"*131071,"b"*131071], executable='/bin/bash',stdout=open("/dev/null","w")) 

Pero una sola cadena arg no puede tener más de 131071 bytes.

Esta otra pregunta es similar a la suya, pero para Windows. Como en ese escenario, puede evitar cualquier limitación de shell evitando la opción shell=True .

De lo contrario, puede proporcionar una lista de archivos a subprocess.Popen() como se hizo en ese escenario, y como lo sugiere @Aaron Digulla.