Cómo ejecutar un programa o llamar a un comando del sistema desde Python

¿Cómo se llama a un comando externo (como si lo hubiera escrito en el shell de Unix o en el símbolo del sistema de Windows) desde un script de Python?

preguntado el 18 de septiembre de 08 a las 02:09

30 Respuestas

Utiliza subprocess módulo en la biblioteca estándar:

import subprocess
subprocess.run(["ls", "-l"])

La ventaja de subprocess.run encima os.system es que es más flexible (puede obtener el stdout, stderr,la código de estado "real", mejor manejo de errores, etc ...).

Incluso la documentación para os.system recomienda usar subprocess en lugar:

La subprocess el módulo proporciona instalaciones más potentes para generar nuevos procesos y recuperar sus resultados; usar ese módulo es preferible a usar esta función. Ver el Reemplazo de funciones antiguas con el módulo de subproceso sección en el subprocess documentación para algunas recetas útiles.

En Python 3.4 y versiones anteriores, use subprocess.call en lugar de .run:

subprocess.call(["ls", "-l"])

Respondido 10 Feb 21, 12:02

¿Hay alguna forma de utilizar la sustitución de variables? Es decir, traté de hacer echo $PATH mediante el uso call(["echo", "$PATH"]), pero solo hizo eco de la cadena literal $PATH en lugar de hacer cualquier sustitución. Sé que podría obtener la variable de entorno PATH, pero me pregunto si hay una manera fácil de hacer que el comando se comporte exactamente como si lo hubiera ejecutado en bash. - Kevin Wheeler

@KevinWheeler Tendrás que usar shell=True para que eso funcione. - SethMMorton

@KevinWheeler NO debes usar shell=True, para este propósito Python viene con os.path.expandvars. En tu caso puedes escribir: os.path.expandvars("$PATH"). @SethMMorton reconsidere su comentario -> Por qué no usar shell = True - Murmel

Si deseas crear una lista a partir de un comando con parámetros, una lista que se puede utilizar con subprocess cuando shell=False, luego use shlex.split para una manera fácil de hacer esto docs.python.org/2/library/shlex.html#shlex.split - Daniel F

También puede pasar como una cadena en lugar de una lista de cadenas: subprocess.run("ls -l") - tuket

A continuación, se muestra un resumen de las formas de llamar a programas externos y las ventajas y desventajas de cada uno:

  1. os.system("some_command with args") pasa el comando y los argumentos al shell de su sistema. Esto es bueno porque en realidad puede ejecutar múltiples comandos a la vez de esta manera y configurar tuberías y redirección de entrada / salida. Por ejemplo:

    os.system("some_command < input_file | another_command > output_file")  
    

Sin embargo, si bien esto es conveniente, debe manejar manualmente el escape de caracteres de shell como espacios, etc. Por otro lado, esto también le permite ejecutar comandos que son simplemente comandos de shell y no programas realmente externos. Ver la documentación.

  1. stream = os.popen("some_command with args") hará lo mismo que os.system excepto que le brinda un objeto similar a un archivo que puede usar para acceder a la entrada / salida estándar para ese proceso. Hay otras 3 variantes de popen que manejan la E / S de manera ligeramente diferente. Si pasa todo como una cadena, entonces su comando se pasa al shell; si los pasa como una lista, entonces no necesita preocuparse por escapar de nada. Ver la documentación.

  2. La Popen clase de la subprocess módulo. Esto está destinado a reemplazar os.popen pero tiene la desventaja de ser un poco más complicado en virtud de ser tan completo. Por ejemplo, dirías:

    print subprocess.Popen("echo Hello World", shell=True, stdout=subprocess.PIPE).stdout.read()
    

    en lugar de:

    print os.popen("echo Hello World").read()
    

    pero es bueno tener todas las opciones allí en una clase unificada en lugar de 4 funciones popen diferentes. Ver la documentación.

  3. La call funcionar desde el subprocess módulo. Esto es básicamente como el Popen class y toma todos los mismos argumentos, pero simplemente espera hasta que el comando se complete y le proporcione el código de retorno. Por ejemplo:

    return_code = subprocess.call("echo Hello World", shell=True)  
    

    Vea la documentación.

  4. Si está en Python 3.5 o posterior, puede usar el nuevo subprocess.run función, que es muy parecida a la anterior pero aún más flexible y devuelve una CompletedProcess objeto cuando el comando termina de ejecutarse.

  5. El módulo os también tiene todas las funciones fork / exec / spawn que tendrías en un programa C, pero no recomiendo usarlas directamente.

La subprocess probablemente debería ser el módulo que usa.

Finalmente, tenga en cuenta que para todos los métodos en los que pasa el comando final para que el shell lo ejecute como una cadena y usted es responsable de escapar de él. Hay serias implicaciones de seguridad si no se puede confiar plenamente en alguna parte de la cadena que pasa. Por ejemplo, si un usuario está ingresando alguna o alguna parte de la cadena. Si no está seguro, utilice estos métodos solo con constantes. Para darle una pista de las implicaciones, considere este código:

print subprocess.Popen("echo %s " % user_input, stdout=PIPE).stdout.read()

e imagina que el usuario ingresa algo "mi mamá no me amaba && rm -rf /" que podría borrar todo el sistema de archivos.

Respondido 04 Oct 19, 05:10

Buena respuesta / explicación. ¿Cómo justifica esta respuesta el lema de Python como se describe en este artículo? fastcompany.com/3026446/… "Estilísticamente, Perl y Python tienen filosofías diferentes. El lema más conocido de Perl es" Hay más de una manera de hacerlo ". Python está diseñado para tener una forma obvia de hacerlo" ¡Parece que debería ser al revés! En Perl, solo conozco dos formas de ejecutar un comando: usando back-tick o open. - Jean

Si usa Python 3.5+, use subprocess.run(). docs.python.org/3.5/library/subprocess.html#subprocess.run - fénix

Lo que normalmente se necesita saber es qué se hace con STDOUT y STDERR del proceso hijo, porque si se ignoran, bajo algunas condiciones (bastante comunes), eventualmente el proceso hijo emitirá una llamada al sistema para escribir en STDOUT (¿STDERR también?) eso excedería el búfer de salida proporcionado para el proceso por el sistema operativo, y el sistema operativo hará que se bloquee hasta que algún proceso lea desde ese búfer. Entonces, con las formas actualmente recomendadas, subprocess.run(..), que hace exactamente "Esto no captura stdout o stderr de forma predeterminada". ¿implicar? Qué pasa subprocess.check_output(..) y STDERR? - Evgeni Sergeev

¿Cuál de los comandos que recomendó bloquear mi script? es decir, si quiero ejecutar varios comandos en un for bucle, ¿cómo lo hago sin que bloquee mi script de Python? No me importa la salida del comando, solo quiero ejecutar muchos de ellos. - Charlie Parker

Podría decirse que esto es al revés. La mayoría de la gente solo necesita subprocess.run() o sus hermanos mayores subprocess.check_call() et al. Para los casos en los que estos no son suficientes, consulte subprocess.Popen(). os.popen() tal vez no debería ser mencionado en absoluto, o venir incluso después de "hackear su propio código fork / exec / spawn". - triples

Implementación típica:

import subprocess

p = subprocess.Popen('ls', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
for line in p.stdout.readlines():
    print line,
retval = p.wait()

Eres libre de hacer lo que quieras con el stdout datos en la tubería. De hecho, puede simplemente omitir esos parámetros (stdout= y stderr=) y se comportará como os.system().

Respondido 04 Oct 19, 05:10

.readlines() lee todas líneas a la vez, es decir, se bloquea hasta que el subproceso sale (cierra su extremo de la tubería). Para leer en tiempo real (si no hay problemas de almacenamiento en búfer) puede: for line in iter(p.stdout.readline, ''): print line, - jfs

¿Podría explicar lo que quiere decir con "si no hay problemas de almacenamiento en búfer"? Si el proceso se bloquea definitivamente, la llamada al subproceso también se bloquea. Lo mismo podría suceder también con mi ejemplo original. ¿Qué más podría pasar con respecto al almacenamiento en búfer? - EmmEff

el proceso hijo puede usar búfer de bloques en modo no interactivo en lugar de búfer de línea, por lo que p.stdout.readline() (nota: no s al final) no verá ningún dato hasta que el niño llene su búfer. Si el niño no produce muchos datos, la salida no será en tiempo real. Vea la segunda razón en P: ¿Por qué no usar una tubería (popen ())?. Se proporcionan algunas soluciones en esta respuesta (pexpect, pty, stdbuf) - jfs

el problema del almacenamiento en búfer solo importa si desea una salida en tiempo real y no se aplica a su código que no imprime nada hasta todas se reciben datos - jfs

Esta respuesta estuvo bien para su época, pero ya no deberíamos recomendar Popen para tareas sencillas. Esto también especifica innecesariamente shell=True. Prueba uno de los subprocess.run() respuestas. - triples

Algunas sugerencias para separar el proceso hijo del que llama (iniciando el proceso hijo en segundo plano).

Suponga que desea iniciar una tarea larga desde un script CGI. Es decir, el proceso hijo debería vivir más que el proceso de ejecución del script CGI.

El ejemplo clásico de la documentación del módulo de subproceso es:

import subprocess
import sys

# Some code here

pid = subprocess.Popen([sys.executable, "longtask.py"]) # Call subprocess

# Some more code here

La idea aquí es que no desea esperar en la línea 'llamar al subproceso' hasta que termine longtask.py. Pero no está claro qué sucede después de la línea "algo más de código aquí" del ejemplo.

Mi plataforma de destino era FreeBSD, pero el desarrollo estaba en Windows, así que primero enfrenté el problema en Windows.

En Windows (Windows XP), el proceso principal no finalizará hasta que longtask.py haya terminado su trabajo. No es lo que quieres en un script CGI. El problema no es específico de Python; en la comunidad PHP los problemas son los mismos.

La solución es pasar DETACHED_PROCESS Bandera de creación de proceso a la función CreateProcess subyacente en la API de Windows. Si tiene instalado pywin32, puede importar el indicador desde el módulo win32process, de lo contrario, debe definirlo usted mismo:

DETACHED_PROCESS = 0x00000008

pid = subprocess.Popen([sys.executable, "longtask.py"],
                       creationflags=DETACHED_PROCESS).pid

/* UPD 2015.10.27 @eryksun en un comentario a continuación señala que la bandera semánticamente correcta es CREATE_NEW_CONSOLE (0x00000010) * /

En FreeBSD tenemos otro problema: cuando finaliza el proceso padre, también finaliza el proceso hijo. Y eso tampoco es lo que quieres en un script CGI. Algunos experimentos mostraron que el problema parecía estar en compartir sys.stdout. Y la solución de trabajo fue la siguiente:

pid = subprocess.Popen([sys.executable, "longtask.py"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)

No he comprobado el código en otras plataformas y no conozco las razones del comportamiento en FreeBSD. Si alguien lo sabe, comparta sus ideas. Buscar en Google sobre el inicio de procesos en segundo plano en Python aún no arroja ninguna luz.

respondido 30 nov., 19:00

Me di cuenta de una posible "peculiaridad" con el desarrollo de aplicaciones py2exe en pydev + eclipse. pude decir que la secuencia de comandos principal no se separó porque la ventana de salida de eclipse no estaba terminando; incluso si el script se ejecuta hasta su finalización, todavía está esperando devoluciones. pero, cuando intenté compilar en un ejecutable py2exe, se produce el comportamiento esperado (ejecuta los procesos como separados, luego se cierra). No estoy seguro, pero el nombre del ejecutable ya no está en la lista de procesos. esto funciona para todos los enfoques (os.system ("start *"), os.spawnl con os.P_DETACH, subprocs, etc.) - maranas

es posible que también necesite la marca CREATE_NEW_PROCESS_GROUP. Ver Popen esperando el proceso hijo incluso cuando el hijo inmediato ha terminado - jfs

Lo siguiente es incorrecto: "[o] n windows (win xp), el proceso principal no finalizará hasta que longtask.py haya terminado su trabajo". El padre saldrá normalmente, pero la ventana de la consola (instancia de conhost.exe) solo se cierra cuando sale el último proceso adjunto, y el hijo puede haber heredado la consola del padre. Configuración DETACHED_PROCESS in creationflags evita esto evitando que el niño herede o cree una consola. Si en cambio desea una nueva consola, use CREATE_NEW_CONSOLE (0x00000010). - Eryk Sun

No quise decir que la ejecución como un proceso independiente sea incorrecta. Dicho esto, es posible que deba configurar los identificadores estándar para archivos, tuberías o os.devnull porque algunos programas de consola salen con un error de lo contrario. Cree una nueva consola cuando desee que el proceso secundario interactúe con el usuario al mismo tiempo que el proceso principal. Sería confuso intentar hacer ambas cosas en una sola ventana. - Eryk Sun

¿No existe una forma independiente del sistema operativo de ejecutar el proceso en segundo plano? - Charlie Parker

import os
os.system("your command")

Tenga en cuenta que esto es peligroso, ya que el comando no se limpia. Dejo que usted busque en Google la documentación relevante sobre los módulos 'os' y 'sys'. Hay un montón de funciones (exec * y spawn *) que harán cosas similares.

Respondido el 03 de junio de 18 a las 20:06

No tengo idea de lo que quise decir hace casi una década (¡verifique la fecha!), Pero si tuviera que adivinar, sería que no se realizó ninguna validación. - ágil

Esto debería apuntar ahora a subprocess como una solución un poco más versátil y portátil. La ejecución de comandos externos es, por supuesto, intrínsecamente intransitable (debe asegurarse de que el comando esté disponible en todas las arquitecturas que necesita admitir) y pasar la entrada del usuario como un comando externo es intrínsecamente inseguro. - triples

Tenga en cuenta la marca de tiempo de este tipo: la respuesta "correcta" tiene 40 veces los votos y es la respuesta n. ° 1. - ágil

La única solución que funcionó para mí para ejecutar cosas de NodeJS. - Nikolay Shindarov

Recomiendo usar el subproceso module en lugar de os.system porque hace un escape de shell por usted y por lo tanto es mucho más seguro.

subprocess.call(['ping', 'localhost'])

Respondido 24 Feb 20, 04:02

Si deseas crear una lista a partir de un comando con parámetros, una lista que se puede utilizar con subprocess cuando shell=False, luego use shlex.split para una manera fácil de hacer esto docs.python.org/2/library/shlex.html#shlex.split (es la forma recomendada según los documentos docs.python.org/2/library/subprocess.html#popen-constructor) - Daniel F

Esto es incorrecto: "Hace que el caparazón se escape por ti y, por lo tanto, es mucho más seguro.". el subproceso no escapa del shell, el subproceso no pasa su comando a través del shell, por lo que no hay necesidad de escapar del shell. - Mentira ryan

import os
cmd = 'ls -al'
os.system(cmd)

Si desea devolver los resultados del comando, puede usar os.popen. Sin embargo, esto está en desuso desde la versión 2.6 a favor de la módulo de subproceso, que otras respuestas han cubierto bien.

Respondido el 26 de enero de 16 a las 19:01

También puede guardar su resultado con la llamada os.system, ya que funciona como el propio shell de UNIX, como por ejemplo os.system ('ls -l> test2.txt') - Stefan Gruenwald

Hay muchas bibliotecas diferentes que le permiten llamar a comandos externos con Python. Para cada biblioteca, he dado una descripción y he mostrado un ejemplo de cómo llamar a un comando externo. El comando que usé como ejemplo es ls -l (enumere todos los archivos). Si desea obtener más información sobre cualquiera de las bibliotecas que enumeré y vinculé la documentación para cada una de ellas.

Fuentes:

Estas son todas las bibliotecas:

Con suerte, esto le ayudará a tomar una decisión sobre qué biblioteca utilizar :)

subproceso

El subproceso le permite llamar a comandos externos y conectarlos a sus conductos de entrada / salida / error (stdin, stdout y stderr). El subproceso es la opción predeterminada para ejecutar comandos, pero a veces otros módulos son mejores.

subprocess.run(["ls", "-l"]) # Run command
subprocess.run(["ls", "-l"], stdout=subprocess.PIPE) # This will run the command and return any output
subprocess.run(shlex.split("ls -l")) # You can also use the shlex library to split the command

os

os se utiliza para "funcionalidad dependiente del sistema operativo". También se puede utilizar para llamar a comandos externos con os.system y os.popen (Nota: también hay un subprocess.popen). os siempre ejecutará el shell y es una alternativa simple para las personas que no lo necesitan o no saben cómo usar subprocess.run.

os.system("ls -l") # run command
os.popen("ls -l").read() # This will run the command and return any output

sh

sh es una interfaz de subproceso que le permite llamar a programas como si fueran funciones. Esto es útil si desea ejecutar un comando varias veces.

sh.ls("-l") # Run command normally
ls_cmd = sh.Command("ls") # Save command as a variable
ls_cmd() # Run command as if it were a function

mi fontanero

plumbum es una biblioteca para programas Python "tipo script". Puede llamar a programas como funciones como en sh. Plumbum es útil si desea ejecutar una tubería sin el shell.

ls_cmd = plumbum.local("ls -l") # get command
ls_cmd() # run command

esperar

pexpect le permite generar aplicaciones secundarias, controlarlas y encontrar patrones en su salida. Esta es una mejor alternativa al subproceso para comandos que esperan un tty en Unix.

pexpect.run("ls -l") # Run command as normal
child = pexpect.spawn('scp foo user@example.com:.') # Spawns child application
child.expect('Password:') # When this is the output
child.sendline('mypassword')

material

fabric es una biblioteca de Python 2.5 y 2.7. Le permite ejecutar comandos de shell locales y remotos. Fabric es una alternativa simple para ejecutar comandos en un shell seguro (SSH)

fabric.operations.local('ls -l') # Run command as normal
fabric.operations.local('ls -l', capture = True) # Run command and receive output

enviado

Envoy se conoce como "subproceso para humanos". Se utiliza como envoltorio de conveniencia alrededor del subprocess módulo.

r = envoy.run("ls -l") # Run command
r.std_out # get output

comandos

commands contiene funciones contenedoras para os.popen, pero se ha eliminado de Python 3 desde subprocess Es una mejor alternativa.

La edición se basó en el comentario de JF Sebastian.

contestado el 29 de mayo de 17 a las 02:05

Yo siempre uso fabric para esto cosas como:

from fabric.operations import local
result = local('ls', capture=True)
print "Content:/n%s" % (result, )

Pero esta parece ser una buena herramienta: sh (Interfaz de subproceso de Python).

Mira un ejemplo:

from sh import vgdisplay
print vgdisplay()
print vgdisplay('-v')
print vgdisplay(v=True)

respondido 30 nov., 19:00

Con la biblioteca estándar

Utiliza módulo de subproceso (Python 3):

import subprocess
subprocess.run(['ls', '-l'])

Es la forma estándar recomendada. Sin embargo, las tareas más complicadas (canalizaciones, salida, entrada, etc.) pueden ser tediosas de construir y escribir.

Nota sobre la versión de Python: si todavía usa Python 2, subprocess.call funciona de manera similar.

ProTip: shlex.split puede ayudarlo a analizar el comando para run, call, y otros subprocess funciones en caso de que no desee (¡o no pueda!), proporciónelas en forma de listas:

import shlex
import subprocess
subprocess.run(shlex.split('ls -l'))

Con dependencias externas

Si no le importan las dependencias externas, utilice mi fontanero:

from plumbum.cmd import ifconfig
print(ifconfig['wlan0']())

Es lo mejor subprocess envoltura. Es multiplataforma, es decir, funciona tanto en Windows como en sistemas similares a Unix. Instalar por pip install plumbum.

Otra biblioteca popular es sh:

from sh import ifconfig
print(ifconfig('wlan0'))

Sin embargo, sh abandonó el soporte de Windows, por lo que no es tan impresionante como solía ser. Instalar por pip install sh.

respondido 30 nov., 19:00

Consulte también la biblioteca de Python "pexpect".

Permite el control interactivo de programas / comandos externos, incluso ssh, ftp, telnet, etc. Puede escribir algo como:

child = pexpect.spawn('ftp 192.168.0.24')

child.expect('(?i)name .*: ')

child.sendline('anonymous')

child.expect('(?i)password')

contestado el 29 de mayo de 17 a las 02:05

Si necesita la salida del comando que está llamando, puede usar subprocess.check_output (Python 2.7+).

>>> subprocess.check_output(["ls", "-l", "/dev/null"])
'crw-rw-rw- 1 root root 1, 3 Oct 18  2007 /dev/null\n'

También tenga en cuenta el shell parámetro.

Si 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 tuberías de shell, comodines de nombre de archivo, expansión de variables de entorno y expansión de ~ a la casa de un usuario. directorio. Sin embargo, tenga en cuenta que Python en sí mismo ofrece implementaciones de muchas características similares a shell (en particular, glob, fnmatch, os.walk(), os.path.expandvars(), os.path.expanduser(), shutil).

Respondido el 03 de junio de 18 a las 23:06

Tenga en cuenta que check_output requiere una lista en lugar de una cadena. Si no confía en los espacios entre comillas para que su llamada sea válida, la forma más sencilla y legible de hacerlo es subprocess.check_output("ls -l /dev/null".split()). - Bruno Bronosky

Así es como ejecuto mis comandos. Este código tiene todo lo que necesitas prácticamente

from subprocess import Popen, PIPE
cmd = "ls -l ~/"
p = Popen(cmd , shell=True, stdout=PIPE, stderr=PIPE)
out, err = p.communicate()
print "Return code: ", p.returncode
print out.rstrip(), err.rstrip()

Respondido 28 Oct 12, 09:10

Creo que es aceptable para comandos codificados de forma rígida, si aumenta la legibilidad. - Adam Matan

Actualizar:

subprocess.run es el enfoque recomendado a partir de Python 3.5 si su código no necesita mantener la compatibilidad con versiones anteriores de Python. Es más consistente y ofrece una facilidad de uso similar a la de Envoy. (Sin embargo, la instalación de tuberías no es tan sencilla. Consulte esta pregunta de cómo.)

Aquí hay algunos ejemplos de la documentación.

Ejecute un proceso:

>>> subprocess.run(["ls", "-l"])  # Doesn't capture output
CompletedProcess(args=['ls', '-l'], returncode=0)

Aumento en ejecución fallida:

>>> subprocess.run("exit 1", shell=True, check=True)
Traceback (most recent call last):
  ...
subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1

Capturar salida:

>>> subprocess.run(["ls", "-l", "/dev/null"], stdout=subprocess.PIPE)
CompletedProcess(args=['ls', '-l', '/dev/null'], returncode=0,
stdout=b'crw-rw-rw- 1 root root 1, 3 Jan 23 16:23 /dev/null\n')

Respuesta original:

Recomiendo probar Enviado. Es un contenedor para subprocesos, que a su vez tiene como objetivo reemplazar los módulos y funciones más antiguos. Envoy es un subproceso para humanos.

Ejemplo de uso de el README:

>>> r = envoy.run('git config', data='data to pipe in', timeout=2)

>>> r.status_code
129
>>> r.std_out
'usage: git config [options]'
>>> r.std_err
''

Ponga cosas alrededor también:

>>> r = envoy.run('uptime | pbcopy')

>>> r.command
'pbcopy'
>>> r.status_code
0

>>> r.history
[<Response 'uptime'>]

respondido 30 nov., 19:00

Utilización de subproceso.

... o para un comando muy simple:

import os
os.system('cat testfile')

respondido 30 nov., 19:00

Llamar a un comando externo en Python

Sencillo, uso subprocess.run, que devuelve un CompletedProcess :

>>> import subprocess
>>> completed_process = subprocess.run('python --version')
Python 3.6.1 :: Anaconda 4.4.0 (64-bit)
>>> completed_process
CompletedProcess(args='python --version', returncode=0)

¿Por qué?

A partir de Python 3.5, la documentación recomienda subprocess.run:

El enfoque recomendado para invocar subprocesos es usar la función run () para todos los casos de uso que puede manejar. Para casos de uso más avanzados, la interfaz Popen subyacente se puede utilizar directamente.

Aquí hay un ejemplo del uso más simple posible, y hace exactamente lo que se le pide:

>>> import subprocess
>>> completed_process = subprocess.run('python --version')
Python 3.6.1 :: Anaconda 4.4.0 (64-bit)
>>> completed_process
CompletedProcess(args='python --version', returncode=0)

run espera a que el comando finalice con éxito, luego devuelve un CompletedProcess objeto. En cambio, puede aumentar TimeoutExpired (si le das un timeout= argumento) o CalledProcessError (si falla y pasas check=True).

Como puede inferir del ejemplo anterior, stdout y stderr se canalizan a su propio stdout y stderr de forma predeterminada.

Podemos inspeccionar el objeto devuelto y ver el comando que se dio y el código de retorno:

>>> completed_process.args
'python --version'
>>> completed_process.returncode
0

Capturando salida

Si desea capturar la salida, puede pasar subprocess.PIPE al apropiado stderr or stdout:

>>> cp = subprocess.run('python --version', 
                        stderr=subprocess.PIPE, 
                        stdout=subprocess.PIPE)
>>> cp.stderr
b'Python 3.6.1 :: Anaconda 4.4.0 (64-bit)\r\n'
>>> cp.stdout
b''

(Me parece interesante y un poco contradictorio que la información de la versión se ponga en stderr en lugar de stdout).

Pasar una lista de comandos

Uno podría pasar fácilmente de proporcionar manualmente una cadena de comando (como sugiere la pregunta) a proporcionar una cadena construida mediante programación. No cree cadenas mediante programación. Este es un problema de seguridad potencial. Es mejor asumir que no confía en la entrada.

>>> import textwrap
>>> args = ['python', textwrap.__file__]
>>> cp = subprocess.run(args, stdout=subprocess.PIPE)
>>> cp.stdout
b'Hello there.\r\n  This is indented.\r\n'

Nota, solo args debe pasarse posicionalmente.

Firma completa

Aquí está la firma real en la fuente y como se muestra en help(run):

def run(*popenargs, input=None, timeout=None, check=False, **kwargs):

La popenargs y kwargs se dan a la Popen constructor. input puede ser una cadena de bytes (o Unicode, si se especifica codificación o universal_newlines=True) que se canalizará al stdin del subproceso.

La documentación describe timeout= y check=True mejor de lo que pude:

El argumento de tiempo de espera se pasa a Popen.communicate (). Si el tiempo de espera expira, el proceso hijo se cerrará y se esperará. La excepción TimeoutExpired se volverá a generar después de que finalice el proceso secundario.

Si la comprobación es verdadera y el proceso finaliza con un código de salida distinto de cero, se generará una excepción CalledProcessError. Los atributos de esa excepción contienen los argumentos, el código de salida y stdout y stderr si fueron capturados.

y este ejemplo para check=True es mejor de lo que se me ocurrió:

>>> subprocess.run("exit 1", shell=True, check=True)
Traceback (most recent call last):
  ...
subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1

Firma ampliada

Aquí hay una firma ampliada, como se indica en la documentación:

subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None, 
shell=False, cwd=None, timeout=None, check=False, encoding=None, 
errors=None)

Tenga en cuenta que esto indica que solo la lista de argumentos debe pasarse posicionalmente. Así que pase los argumentos restantes como argumentos de palabras clave.

Popen

Cuando uso Popen ¿en lugar de? Me costaría encontrar un caso de uso basado solo en los argumentos. Uso directo de Popen Sin embargo, le daría acceso a sus métodos, incluidos poll, 'enviar_señal', 'terminar' y 'esperar'.

Este es el Popen firma como se indica en la fuente. Creo que esta es la encapsulación más precisa de la información (a diferencia de help(Popen)):

def __init__(self, args, bufsize=-1, executable=None,
             stdin=None, stdout=None, stderr=None,
             preexec_fn=None, close_fds=_PLATFORM_DEFAULT_CLOSE_FDS,
             shell=False, cwd=None, env=None, universal_newlines=False,
             startupinfo=None, creationflags=0,
             restore_signals=True, start_new_session=False,
             pass_fds=(), *, encoding=None, errors=None):

Pero más informativo es que el Popen documentación:

subprocess.Popen(args, bufsize=-1, executable=None, stdin=None,
                 stdout=None, stderr=None, preexec_fn=None, close_fds=True,
                 shell=False, cwd=None, env=None, universal_newlines=False,
                 startupinfo=None, creationflags=0, restore_signals=True,
                 start_new_session=False, pass_fds=(), *, encoding=None, errors=None)

Ejecute un programa hijo en un proceso nuevo. En POSIX, la clase usa un comportamiento similar a os.execvp () para ejecutar el programa hijo. En Windows, la clase usa la función CreateProcess () de Windows. Los argumentos de Popen son los siguientes.

Comprender la documentación restante sobre Popen se dejará como ejercicio para el lector.

Respondido 18 Oct 17, 19:10

Aquí puede encontrar un ejemplo simple de comunicación bidireccional entre un proceso primario y un subproceso: stackoverflow.com/a/52841475/1349673 - James Hirschorn

El primer ejemplo probablemente debería tener shell=True o (mejor aún) pasar el comando como una lista. - triples

os.system está bien, pero un poco anticuado. Tampoco es muy seguro. En su lugar, intente subprocess. subprocess no llama directamente a sh y, por lo tanto, es más seguro que os.system.

Obtener mas informacion acá.

Respondido el 10 de diciembre de 16 a las 16:12

Si bien estoy de acuerdo con la recomendación general, subprocess no elimina todos los problemas de seguridad y tiene algunos problemas propios. - triples

También hay Plumbum

>>> from plumbum import local
>>> ls = local["ls"]
>>> ls
LocalCommand(<LocalPath /bin/ls>)
>>> ls()
u'build.py\ndist\ndocs\nLICENSE\nplumbum\nREADME.rst\nsetup.py\ntests\ntodo.txt\n'
>>> notepad = local["c:\\windows\\notepad.exe"]
>>> notepad()                                   # Notepad window pops up
u''                                             # Notepad window is closed by user, command returns

Respondido 10 Oct 14, 21:10

Puede ser así de simple:

import os
cmd = "your command"
os.system(cmd)

Respondido el 08 de junio de 18 a las 15:06

Esto no señala los inconvenientes, que se explican con mucho más detalle en PEP-324. La documentación para os.system recomienda explícitamente evitarlo en favor de subprocess. - triples

Uso:

import os

cmd = 'ls -al'

os.system(cmd)

os: este módulo proporciona una forma portátil de utilizar la funcionalidad dependiente del sistema operativo.

Para los más os funciones, acá es la documentación.

contestado el 29 de mayo de 17 a las 02:05

también está en desuso. usar subproceso - Corey Goldberg

me gusta bastante shell_command por su sencillez. Está construido sobre el módulo de subproceso.

Aquí tienes un ejemplo de la documentación:

>>> from shell_command import shell_call
>>> shell_call("ls *.py")
setup.py  shell_command.py  test_shell_command.py
0
>>> shell_call("ls -l *.py")
-rw-r--r-- 1 ncoghlan ncoghlan  391 2011-12-11 12:07 setup.py
-rw-r--r-- 1 ncoghlan ncoghlan 7855 2011-12-11 16:16 shell_command.py
-rwxr-xr-x 1 ncoghlan ncoghlan 8463 2011-12-11 16:17 test_shell_command.py
0

respondido 30 nov., 19:00

Aquí hay otra diferencia que no se mencionó anteriormente.

subprocess.Popen ejecuta el como un subproceso. En mi caso, necesito ejecutar un archivo que necesita comunicarse con otro programa ,.

Intenté el subproceso y la ejecución fue exitosa. Sin embargo , no se pudo comunicar con . Todo es normal cuando ejecuto ambos desde la terminal.

Una más: (NOTA: kwrite se comporta de manera diferente a otras aplicaciones. Si prueba lo siguiente con Firefox, los resultados no serán los mismos).

Si intentas os.system("kwrite"), el flujo del programa se congela hasta que el usuario cierra kwrite. Para superar eso intenté en cambio os.system(konsole -e kwrite). Esta vez el programa siguió fluyendo, pero kwrite se convirtió en el subproceso de la consola.

Cualquiera ejecuta kwrite sin ser un subproceso (es decir, en el monitor del sistema debe aparecer en el borde más a la izquierda del árbol).

Respondido el 03 de junio de 18 a las 23:06

Que quieres decir con "Cualquiera ejecuta kwrite sin ser un subproceso"? - Peter Mortensen

os.system no le permite almacenar resultados, por lo que si desea almacenar resultados en alguna lista o algo, un subprocess.call obras.

respondido 30 nov., 19:00

subprocess.check_call es conveniente si no desea probar los valores devueltos. Lanza una excepción en cualquier error.

Respondido el 18 de enero de 11 a las 22:01

Yo tiendo a usar subproceso Junto con shlex (para manejar el escape de cadenas entre comillas):

>>> import subprocess, shlex
>>> command = 'ls -l "/your/path/with spaces/"'
>>> call_params = shlex.split(command)
>>> print call_params
["ls", "-l", "/your/path/with spaces/"]
>>> subprocess.call(call_params)

Respondido 30 Abr '14, 18:04

Enchufe desvergonzado, escribí una biblioteca para esto: P https://github.com/houqp/shell.py

Es básicamente una envoltura para popen y shlex por ahora. También admite comandos de canalización para que pueda encadenar comandos más fácilmente en Python. Entonces puedes hacer cosas como:

ex('echo hello shell.py') | "awk '{print $2}'"

contestado el 02 de mayo de 14 a las 00:05

En Windows, puede importar el subprocess módulo y ejecutar comandos externos llamando subprocess.Popen(), subprocess.Popen().communicate() y subprocess.Popen().wait() como a continuación:

# Python script to run a command line
import subprocess

def execute(cmd):
    """
        Purpose  : To execute a command and return exit status
        Argument : cmd - command to execute
        Return   : exit_code
    """
    process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    (result, error) = process.communicate()

    rc = process.wait()

    if rc != 0:
        print "Error: failed to execute command:", cmd
        print error
    return result
# def

command = "tasklist | grep python"
print "This process detail: \n", execute(command)

Salida:

This process detail:
python.exe                     604 RDP-Tcp#0                  4      5,660 K

contestado el 29 de mayo de 17 a las 02:05

Puede usar Popen y luego puede verificar el estado del procedimiento:

from subprocess import Popen

proc = Popen(['ls', '-l'])
if proc.poll() is None:
    proc.kill()

Más info: subproceso.Popen.

contestado el 29 de mayo de 17 a las 02:05

Para obtener la identificación de la red del Pila abierta Neutrón:

#!/usr/bin/python
import os
netid = "nova net-list | awk '/ External / { print $2 }'"
temp = os.popen(netid).read()  /* Here temp also contains new line (\n) */
networkId = temp.rstrip()
print(networkId)

Salida de nova net-list

+--------------------------------------+------------+------+
| ID                                   | Label      | CIDR |
+--------------------------------------+------------+------+
| 431c9014-5b5d-4b51-a357-66020ffbb123 | test1      | None |
| 27a74fcd-37c0-4789-9414-9531b7e3f126 | External   | None |
| 5a2712e9-70dc-4b0e-9281-17e02f4684c9 | management | None |
| 7aa697f5-0e60-4c15-b4cc-9cb659698512 | Internal   | None |
+--------------------------------------+------------+------+

Salida de imprimir (networkId)

27a74fcd-37c0-4789-9414-9531b7e3f126

respondido 30 nov., 19:01

No deberías recomendar os.popen() en 2016. El script Awk podría reemplazarse fácilmente con código Python nativo. - triples

En Linux, en caso de que desee llamar a un comando externo que se ejecutará de forma independiente (seguirá ejecutándose después de que termine el script de Python), puede usar una cola simple como cola de tareas o las at comando

Un ejemplo con el spooler de tareas:

import os
os.system('ts <your-command>')

Notas sobre el administrador de trabajos en cola de tareas (ts):

  1. Puede establecer el número de procesos simultáneos que se ejecutarán ("ranuras") con:

    ts -S <number-of-slots>

  2. Instalación ts no requiere privilegios de administrador. Puede descargarlo y compilarlo desde la fuente con un simple make, agréguelo a su ruta y listo.

respondido 27 nov., 16:03

ts no es estándar en ninguna distribución que conozca, aunque el puntero a at es levemente útil. Probablemente también deberías mencionar batch. Como en otros lugares, el os.system() recomendación probablemente debería al menos mencionar que subprocess es su reemplazo recomendado. - triples

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.