Pertanyaan Menyaring output standar subproses ke variabel


Saya ingin menjalankan perintah pythong, menggunakan modul subprocess, dan menyimpan output dalam sebuah variabel. Namun, saya tidak ingin output perintah untuk dicetak ke terminal. Untuk kode ini:

def storels():
   a = subprocess.Popen("ls",shell=True)
storels()

Saya mendapatkan daftar direktori di terminal, alih-alih menyimpannya di dalamnya a. Saya juga sudah mencoba:

 def storels():
       subprocess.Popen("ls > tmp",shell=True)
       a = open("./tmp")
       [Rest of Code]
 storels()

Ini juga mencetak output dari ls ke terminal saya. Saya bahkan sudah mencoba perintah ini dengan metode os.system yang agak tertanggal, sejak dijalankan ls > tmp di terminal tidak mencetak ls ke terminal sama sekali, tapi menyimpannya tmp. Namun, hal yang sama terjadi.

Edit:

Saya mendapatkan kesalahan berikut setelah mengikuti saran marcog, tetapi hanya ketika menjalankan perintah yang lebih kompleks. cdrecord --help. Python memuntahkan ini:

Traceback (most recent call last):
  File "./install.py", line 52, in <module>
    burntrack2("hi")
  File "./install.py", line 46, in burntrack2
    a = subprocess.Popen("cdrecord --help",stdout = subprocess.PIPE)
  File "/usr/lib/python2.6/subprocess.py", line 633, in __init__
    errread, errwrite)
  File "/usr/lib/python2.6/subprocess.py", line 1139, in _execute_child
    raise child_exception
OSError: [Errno 2] No such file or directory

75
2017-12-22 23:45


asal


Jawaban:


Untuk mendapatkan output ls, gunakan stdout=subprocess.PIPE.

>>> proc = subprocess.Popen('ls', stdout=subprocess.PIPE)
>>> output = proc.stdout.read()
>>> print output
bar
baz
foo

Perintah cdrecord --help output ke stderr, jadi Anda perlu pipa yang lekat. Anda juga harus memecah perintah ke dalam daftar token seperti yang telah saya lakukan di bawah ini, atau alternatifnya adalah untuk lulus shell=True argumen tetapi ini membakar shell sepenuhnya-meledak yang dapat berbahaya jika Anda tidak mengontrol isi string perintah.

>>> proc = subprocess.Popen(['cdrecord', '--help'], stderr=subprocess.PIPE)
>>> output = proc.stderr.read()
>>> print output
Usage: wodim [options] track1...trackn
Options:
    -version    print version information and exit
    dev=target  SCSI target to use as CD/DVD-Recorder
    gracetime=# set the grace time before starting to write to #.
...

Jika Anda memiliki perintah yang menghasilkan stdout dan stderr dan Anda ingin menggabungkannya, Anda dapat melakukannya dengan mem-pipe stderr ke stdout dan kemudian menangkap stdout.

subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

Seperti yang disebutkan oleh Chris Morgan, Anda harus menggunakan proc.communicate() dari pada proc.read().

>>> proc = subprocess.Popen(['cdrecord', '--help'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
>>> out, err = proc.communicate()
>>> print 'stdout:', out
stdout: 
>>> print 'stderr:', err
stderr:Usage: wodim [options] track1...trackn
Options:
    -version    print version information and exit
    dev=target  SCSI target to use as CD/DVD-Recorder
    gracetime=# set the grace time before starting to write to #.
...

112
2017-12-22 23:49



Jika Anda menggunakan python 2.7 atau yang lebih baru, cara termudah untuk melakukannya adalah dengan menggunakan subprocess.check_output() perintah. Berikut ini contohnya:

output = subprocess.check_output('ls')

Untuk juga mengarahkan stderr Anda dapat menggunakan yang berikut:

output = subprocess.check_output('ls', stderr=subprocess.STDOUT)



Dalam hal Anda ingin melewatkan parameter ke perintah, Anda dapat menggunakan daftar atau menggunakan shell dan menggunakan satu string.

output = subprocess.check_output(['ls', '-a'])
output = subprocess.check_output('ls -a', shell=True)

23
2018-03-16 18:25



Dengan a = subprocess.Popen("cdrecord --help",stdout = subprocess.PIPE) , Anda perlu menggunakan daftar atau menggunakan shell=True;

Salah satu dari ini akan bekerja. Yang pertama lebih disukai.

a = subprocess.Popen(['cdrecord', '--help'], stdout=subprocess.PIPE)

a = subprocess.Popen('cdrecord --help', shell=True, stdout=subprocess.PIPE)

Juga, daripada menggunakan Popen.stdout.read/Popen.stderr.read, kamu harus menggunakan .communicate() (lihat dokumentasi subproses untuk alasannya).

proc = subprocess.Popen(['cdrecord', '--help'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = proc.communicate()

10
2017-12-23 00:17