Domanda

Qual è l'equivalente dei backtick trovati in Ruby e Perl in Python? Cioè, in Ruby posso farlo:

foo = `cat /tmp/baz`

Che aspetto ha l'istruzione equivalente in Python? Ho provato os.system (" cat / tmp / baz ") ma questo mette il risultato fuori standard e mi restituisce il codice di errore di quell'operazione.

È stato utile?

Soluzione

output = os.popen('cat /tmp/baz').read()

Altri suggerimenti

Il modo più flessibile è utilizzare il sottoprocesso modulo:

import subprocess

out = subprocess.run(["cat", "/tmp/baz"], capture_output=True)
print("program output:", out)

capture_output è stato introdotto in Python 3.7, per le versioni precedenti è invece possibile utilizzare la funzione speciale check_output () :

out = subprocess.check_output(["cat", "/tmp/baz"])

Puoi anche costruire manualmente un oggetto sottoprocesso se hai bisogno di un controllo dettagliato:

proc = subprocess.Popen(["cat", "/tmp/baz"], stdout=subprocess.PIPE)
(out, err) = proc.communicate()

Tutte queste funzioni supportano parametri della parola chiave per personalizzare la modalità di esecuzione del sottoprocesso. Ad esempio, puoi usare shell = True per eseguire il programma attraverso la shell, se hai bisogno di cose come espansioni di nomi di file di * , ma questo viene fornito con limitazioni .

sth ha ragione . Puoi anche usare os.popen (), ma generalmente è preferibile sottoprocesso (Python 2.4+).

Tuttavia, a differenza di alcune lingue che lo incoraggiano, è generalmente considerata una cattiva forma generare un sottoprocesso in cui è possibile fare lo stesso lavoro all'interno della lingua. È più lento, meno affidabile e dipendente dalla piattaforma. Il tuo esempio sarebbe meglio come:

foo= open('/tmp/baz').read()

eta:

  

baz è una directory e sto cercando di ottenere il contenuto di tutti i file in quella directory

? cat su una directory mi dà un errore.

Se vuoi un elenco di file:

import os
foo= os.listdir('/tmp/baz')

Se vuoi il contenuto di tutti i file in una directory, qualcosa del tipo:

contents= []
for leaf in os.listdir('/tmp/baz'):
    path= os.path.join('/tmp/baz', leaf)
    if os.path.isfile(path):
        contents.append(open(path, 'rb').read())
foo= ''.join(contents)

oppure, se puoi essere sicuro che non ci siano directory, puoi inserirla in una riga:

path= '/tmp/baz'
foo= ''.join(open(os.path.join(path, child), 'rb').read() for child in os.listdir(path))
foo = subprocess.check_output(["cat", "/tmp/baz"])

Da Python 3.5 in poi, il modo consigliato è usare subprocess.run . Per ottenere lo stesso comportamento che descrivi, dovresti usare:

output = subprocess.run("ls", shell=True, stdout=subprocess.PIPE).stdout

Questo restituirà un oggetto byte . Potresti voler aggiungere .decode (" ascii ") o .decode (" utf-8 ") alla fine per ottenere un str .

Il modo più semplice è usare il pacchetto comandi.

import commands

commands.getoutput("whoami")

Output:

  

'bganesan'

import os
foo = os.popen('cat /tmp/baz', 'r').read()

Sto usando

  

(6: 0) $ python --version   Python 2.7.1

Uno degli esempi sopra è:

import subprocess
proc = subprocess.Popen(["cat", "/tmp/baz"], stdout=subprocess.PIPE, shell=True)
(out, err) = proc.communicate()
print "program output:", out

Per me, questo non è riuscito ad accedere alla directory / tmp. Dopo aver esaminato la stringa di documenti per sottoprocesso ho sostituito

  

[" prog " ;, " arg "]

con

  

" prog arg "

e ha ottenuto il comportamento di espansione della shell desiderato (a prog Per`s `prog arg`)

  

print subprocess.Popen (" ls -ld / tmp / v * " ;, stdout = subprocess.PIPE, shell = True) .communicate () [0]


Ho smesso di usare Python qualche tempo fa perché ero infastidito dalla difficoltà di fare l'equivalente di perl `cmd ...`. Sono felice di scoprire che Python lo ha reso ragionevole.

Se si utilizza subprocess.Popen, ricordarsi di specificare bufsize. Il valore predefinito è 0, che significa "non bufferizzato", non "scegli un valore predefinito ragionevole".

Questo non funzionerà in python3, ma in python2 puoi estendere str con un metodo __repr__ personalizzato che chiama il tuo comando shell e lo restituisce in questo modo:

#!/usr/bin/env python

import os

class Command(str):
    """Call system commands"""

    def __repr__(cmd):
        return os.popen(cmd).read()

Che puoi usare come

#!/usr/bin/env python
from command import Command

who_i_am = `Command('whoami')`

# Or predeclare your shell command strings
whoami = Command('whoami')
who_i_am = `whoami`

L'operatore backtick (`) è stato rimosso in Python 3 . È confusamente simile a una singola citazione e difficile da scrivere su alcune tastiere. Invece del backtick , usa la funzione integrata equivalente repr () .

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top