Cuándo usar Shell = Verdadero para el módulo de subproceso de Python

Parece que cada vez que trato de usar el módulo de subproceso de Python, encuentro que todavía no entiendo algunas cosas. Actualmente, estaba intentando unir 3 archivos mp4 desde un módulo Python.

Cuando lo intente

z ='MP4Box -cat test_0.mp4 -cat test_1.mp4 -cat test_2.mp4 -new test_012d.mp4' subprocess.Popen(z,shell=True) 

Todo funciono

Cuando lo intente

 z = ['MP4Box', '-cat test_0.mp4', '-cat test_1.mp4', '-cat test_2.mp4', '-new test_012d.mp4'] subprocess.Popen(z,shell=False) 

Tuve el siguiente error:

 Option -cat test_0.mp4 unknown. Please check usage 

Pensé que para shell=False solo necesitaba proporcionar una lista donde el primer elemento era el ejecutable que quería ejecutar y cada elemento posterior era un argumento para ese ejecutable. ¿Estoy equivocado en esta creencia, o hay una manera correcta de crear el comando que quería usar?

Además, ¿hay reglas para usar Shell=True en subprocess.Popen? Hasta ahora, todo lo que sé (?) Es “no lo hagas, puedes exponer tu código a los ataques de inyección de Shell”. ¿Por qué Shell=False evita este problema? ¿Hay alguna vez una ventaja real para usar ‘Shell = True`?

Si el shell es True , el comando especificado se ejecutará a través del shell. Esto puede ser útil si está utilizando Python principalmente para el flujo de control mejorado que ofrece en la mayoría de los shells del sistema y aún desea un acceso conveniente a otras funciones del shell , como shells, comodines de nombre de archivo, expansión de variables de entorno y expansión de ~ a la casa del usuario. directorio.

Cuando shell=True es peligroso?

Si ejecutamos comandos de shell que pueden incluir una entrada sin autorización de una fuente no confiable , hará que un progtwig sea vulnerable a la inyección de shell , un grave defecto de seguridad que puede resultar en la ejecución de comandos arbitrarios. Por esta razón, el uso de shell=True se recomienda en los casos en que la cadena de comandos se construye desde una entrada externa

P.ej. (Tomado de documentos )

 >>> from subprocess import call >>> filename = input("What file would you like to display?\n") What file would you like to display? non_existent; rm -rf / # >>> call("cat " + filename, shell=True) # Uh-oh. This will end badly.. 

Tienes que dar cada argumento individual como un elemento de una lista:

 z = ['MP4Box', '-cat', 'test_0.mp4', '-cat', 'test_1.mp4', '-cat', 'test_2.mp4', '-new', 'test_012d.mp4'] subprocess.Popen(z,shell=False) 

Esto es normalmente lo que quiere hacer, porque no necesita escapar de los caracteres especiales de la shell en los nombres de archivo.