2010-07-26 11 views
11

Spinning off da un altro thread, quando è opportuno usare os.system() per emettere comandi come rm -rf, cd, make, xterm, ls?Python - Quando è corretto usare os.system() per inviare comandi Linux comuni

considerando che ci sono versioni analogiche dei comandi di cui sopra (ad eccezione marca e xterm), sto assumendo è più sicuro da usare questi comandi pitone built-in invece di utilizzare os.system()

Qualche idea? Mi piacerebbe sentirli.

+3

Una cosa da notare oltre alle risposte finora, usando Python come linguaggio "colla" può facilmente sfuggire di mano. Se hai un programma che è quasi interamente l'esecuzione automatica di cose fatte facilmente su una riga di comando, e non sei preoccupato per i sistemi non Unix, perché non usare solo uno script di shell? –

+4

Utilizzare il modulo del processo secondario anziché os.system. Se vuoi un qualche tipo di controllo sul processo, sarai grato. –

risposta

18

Regola generale: se esiste una funzione Python integrata per ottenere questa funzionalità, utilizzare questa funzione. Perché? Rende portatile il tuo codice su diversi sistemi, più sicuro e probabilmente più veloce in quanto non sarà necessario generare un processo aggiuntivo.

+5

Per non parlare: se devi fare molto, l'avvio di molti nuovi processi può essere un problema di prestazioni. –

+0

@Mattias, ottima osservazione, ho aggiornato la mia risposta per tenerne conto. –

4

La risposta di Darin è un buon inizio.

Oltre a ciò, è una questione di quanto portatile pensi di essere. Se il tuo programma funzionerà solo su Linux "standard" e "moderni" ragionevolmente, allora non c'è motivo per te di reinventare la ruota; se provassi a riscrivere make o xterm, manderebbero gli uomini in camice bianco per te. Se funziona e non hai problemi con la piattaforma, buttati fuori e usa semplicemente Python come colla!

Se la compatibilità tra sistemi sconosciuti era un grosso problema, si potrebbe provare a cercare le librerie per fare ciò che è necessario fare in modo indipendente dalla piattaforma. O hai bisogno di cercare un modo per chiamare utility di bordo con nomi, percorsi e meccanismi diversi a seconda del tipo di sistema su cui ti trovi.

2

Si consiglia di utilizzare solo os.system per le cose che non sono già equivalenti all'interno del modulo os. Perché rendere la tua vita più difficile?

3

L'unica volta che os.system potrebbe essere appropriato è per una soluzione rapida e sporca per uno script non di produzione o per qualche tipo di test. Altrimenti, è meglio usare le funzioni integrate.

+0

Ho postato una risposta simile prima di vedere questo ... –

5

Uno dei problemi con system() è che implica la conoscenza della sintassi e del linguaggio della shell per l'analisi e l'esecuzione della riga di comando. Questo crea potenziale per un bug in cui non hai validato correttamente l'input, e la shell potrebbe intercettare qualcosa come la sostituzione di variabili o determinare dove un argomento inizia o finisce in un modo che non ti aspetti. Inoltre, la shell di un altro OS potrebbe avere una sintassi divergente dalla tua, compresa una divergenza molto sottile che non noterai subito. Per ragioni come queste preferisco usare execve() invece di system() - puoi passare direttamente token argv e non devi preoccuparti di qualcosa nel mezzo (mis-) analizzare il tuo input.

Un altro problema con (questo vale anche per l'utilizzo di execve()) è che quando si esegue il codice, si sta dicendo "cerca questo programma e passa questi argomenti". Questo fa un paio di assunzioni che possono portare a bug. Il primo è che il programma esiste e può essere trovato in $PATH. Forse su qualche sistema non lo farà. Secondo, forse su qualche sistema, o anche su una versione futura del proprio sistema operativo, supporterà un diverso insieme di opzioni. In questo senso, eviterei di farlo a meno che non siate assolutamente certi che il sistema su cui girerete avrà il programma. (Come forse hai messo il programma callee sul sistema per cominciare, o il modo in cui lo invocate è mandato da qualcosa come POSIX.)

Infine ... C'è anche un colpo di prestazioni associato alla ricerca del programma giusto, creare un nuovo processo, caricare il programma, ecc.Se stai facendo qualcosa di semplice come un mv, è molto più efficiente usare direttamente la chiamata di sistema.

Questi sono solo alcuni dei motivi per evitare system(). Sicuramente ce ne sono di più.

4

La tua domanda sembra avere due parti. Hai menzionato comandi di chiamata come "xterm", "rm -rf" e "cd".

Nota a margine: non è possibile chiamare "cd" in una sotto-shell. Scommetto che era una domanda trabocchetto ...

Per quanto riguarda le altre cose a livello di comando che potresti voler fare, come "rm -rf SOMETHING", esiste già un equivalente python. Questo risponde alla prima parte della tua domanda. Ma sospetto che tu stia davvero chiedendo della seconda parte.

La seconda parte della domanda può essere riformulata come "dovrei usare system() o qualcosa come il modulo di sottoprocesso?".

Ho una risposta semplice per voi: basta dire NO all'utilizzo di "system()", ad eccezione della prototipazione.

Va bene per verificare che qualcosa funziona, o per quella script "veloce e sporco", ma ci sono troppi problemi con os.system():

  1. si biforca una shell per voi - bene se avete bisogno di uno
  2. si espande wild card per voi - bene a meno che non si dispone di alcun
  3. gestisce reindirizzare - bene se si vuole che
  4. Effettua una copia di output a stderr/stdout e legge da stdin per impostazione predefinita
  5. Cerca di capire il quoting, ma non lo fa molto bene (prova 'Cmd ">" Ofile')
  6. Relativo al # 5, non sempre ingigantisce i confini degli argomenti (es. argomenti con spazi in essi potrebbero essere incasinati)

Basta dire di no a "sistema()"!

1

La chiamata os.system inizia a essere "disapprovata" in python. La "nuova" sostituzione sarebbe subprocess.call o subprocess.Popen nel modulo subprocess. Controlla i documenti per subprocess

L'altra cosa bella del sottoprocesso è che puoi leggere lo stdout e lo stderr in variabili ed elaborarlo senza dover reindirizzare ad altri file.

Come altri hanno già detto, ci sono moduli per la maggior parte delle cose. A meno che tu non stia cercando di incollare molti altri comandi, rimango con le cose incluse nella libreria. Se stai copiando dei file, usa shutil, lavorando con gli archivi hai moduli come tarfile/zipfile e così via.

Buona fortuna.

Problemi correlati