2010-07-26 20 views
11

Al girar desde otro subproceso, cuándo es apropiado usar os.system() para ejecutar comandos como rm -rf, cd, make, xterm, ls?Python - Cuándo es correcto utilizar os.system() para ejecutar comandos comunes de Linux

vista de que hay versiones analógicas de los comandos anteriores (excepto la marca y el xterm), estoy asumiendo que es seguro utilizar estos comandos de Python incorporadas en lugar de utilizar os.system()

¿Alguna idea? Me encantaría escucharlos.

+3

Una cosa a tener en cuenta, además de las respuestas hasta ahora, el uso de Python como un lenguaje "pegamento" puede salir de control fácilmente. Si tiene un programa que es casi completamente la ejecución automatizada de cosas fáciles de hacer en una línea de comando, y no le preocupan los sistemas que no son Unixish, ¿por qué no simplemente usar un script de shell? –

+4

Utilice el módulo de subproceso en lugar de os.system. Si quieres algún tipo de control sobre el proceso, estarás agradecido. –

Respuesta

18

Regla de oro: si hay una función incorporada de Python para lograr esta funcionalidad, use esta función. ¿Por qué? Hace que su código sea portátil en diferentes sistemas, más seguro y probablemente más rápido ya que no habrá necesidad de generar un proceso adicional.

+5

Sin mencionar: si necesita hacerlo mucho, comenzar muchos procesos nuevos puede ser un problema de rendimiento. –

+0

@Mattias, observación excelente, he actualizado mi respuesta para tenerla en cuenta. –

4

La respuesta de Darin es un buen comienzo.

Más allá de eso, se trata de lo portátil que planeas ser. Si su programa solo se ejecutará en un Linux razonablemente "estándar" y "moderno", entonces no hay razón para que reinvente la rueda; si intentas volver a escribir make o xterm enviarían a los hombres con batas blancas para ti. Si funciona y no tienes problemas con la plataforma, ¡olvídate y simplemente utiliza Python como pegamento!

Si la compatibilidad con sistemas desconocidos fuera un gran problema, podría intentar buscar bibliotecas para hacer lo que necesita de una plataforma independiente. O necesita buscar una forma de llamar a las utilidades a bordo con diferentes nombres, rutas y mecanismos dependiendo del tipo de sistema en el que se encuentre.

2

Sugeriría que solo utilice el uso os.system para cosas que ya no existen equivalentes dentro del módulo os. ¿Por qué hacer tu vida más difícil?

3

La única vez que os.system podría ser apropiado es para una solución rápida y sucia para un script que no sea de producción o algún tipo de prueba. De lo contrario, es mejor usar las funciones incorporadas.

+0

Publiqué una respuesta similar antes de ver esto ... –

5

Uno de los problemas con system() es que implica el conocimiento de la sintaxis y el lenguaje del shell para analizar y ejecutar su línea de comandos. Esto crea la posibilidad de un error en el que no validar la entrada correctamente, y el intérprete de comandos puede impulsar algo así como la sustitución de variables o determinar dónde comienza o termina un argumento de una manera que no espera. Además, el shell de otro sistema operativo puede tener una sintaxis divergente de la suya, incluida una divergencia muy sutil que no notará de inmediato. Por razones como estas prefiero usar execve() en lugar de system() - puede pasar tokens argv directamente y no tener que preocuparse por algo en el medio (error-) al analizar su entrada.

Otro problema con system() (esto también se aplica al uso de execve()) es que cuando se codifica eso, se está diciendo, "busque este programa, y ​​páselo por args". Esto hace un par de suposiciones que pueden conducir a errores. Primero es que el programa existe y se puede encontrar en $PATH. Tal vez en algún sistema no lo hará. En segundo lugar, tal vez en algún sistema, o incluso en una versión futura de su propio SO, admitirá un conjunto diferente de opciones. En este sentido, evitaría hacer esto a menos que esté absolutamente seguro de que el sistema en el que se ejecutará tendrá el programa. (Al igual que quizás pusiste el programa callee en el sistema para empezar, o la forma en que lo invocas es algo así como POSIX.)

Por último ... También hay un impacto en el rendimiento asociado con buscar el programa correcto, creando un nuevo proceso, cargando el programa, etc.Si está haciendo algo simple como mv, es mucho más eficiente usar la llamada del sistema directamente.

Estas son solo algunas de las razones para evitar system(). Seguramente hay más.

4

Su pregunta parece tener dos partes. Menciona comandos de llamada como "xterm", "rm -rf" y "cd".

Lado Nota: no puede llamar a 'cd' en un subcance. Apuesto a que fue una pregunta capciosa ...

En cuanto a otras cosas de nivel de comando que podría querer hacer, como "rm -rf ALGO", ya existe un equivalente de python. Esto responde la primera parte de tu pregunta. Pero sospecho que realmente estás preguntando sobre la segunda parte.

La segunda parte de su pregunta se puede reformular como "¿debo usar el sistema() o algo así como el módulo de subproceso?".

Tengo una respuesta simple para usted: simplemente diga NO a usar "sistema()", excepto prototipos.

Está bien para la verificación de que algo funciona, o para el guión "rápida y sucia", pero hay demasiados problemas con os.system():

  1. se bifurca una concha para usted - bien si lo necesita
  2. se expande comodines para usted - bien a menos que usted no tiene ninguna
  3. se ocupa de redirigir - bien si quieres que
  4. vuelca la salida a stderr/stdout y lee de stdin de forma predeterminada
  5. Trata de entender las citas, pero no funciona muy bien (prueba 'Cmd'> 'Ofile')
  6. Relacionado con el # 5, no siempre asimila los límites de los argumentos (es decir, los argumentos con espacios en ellos pueden estropearse)

¡Diga no a "system()"!

1

La llamada al sistema os está empezando a ser "mal vista" en python. El reemplazo 'nuevo' sería subprocess.call o subprocess. Popen en el módulo de subproceso. Compruebe los documentos para subprocess

La otra cosa agradable sobre el subproceso es que puede leer stdout y stderr en variables, y procesar eso sin tener que redirigir a otro archivo (s).

Como otros han dicho anteriormente, hay módulos para la mayoría de las cosas. A menos que intentes unir muchos otros comandos, me quedaré con las cosas incluidas en la biblioteca. Si está copiando archivos, use shutil, trabaje con archivos, tenga módulos como tarfile/zipfile, etc.

Buena suerte.

Cuestiones relacionadas