it-swarm-id.com

Memanggil perintah eksternal dengan Python

Bagaimana saya bisa memanggil perintah eksternal (seolah saya mengetiknya di Unix Shell atau Windows command Prompt) dari dalam skrip Python?

4038
freshWoWer

Lihatlah modul subprocess di perpustakaan standar:

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

Keuntungan dari subprocess vs system adalah lebih fleksibel (Anda bisa mendapatkan stdout, stderr, kode status "nyata", penanganan kesalahan yang lebih baik, dll ...).

Dokumentasi resmi merekomendasikan modul subprocess di atas sistem os.sistem alternatif ():

Modul subprocess menyediakan fasilitas yang lebih kuat untuk menghasilkan proses baru dan mengambil hasilnya; menggunakan modul itu lebih baik daripada menggunakan fungsi ini [ os.system() ].

Bagian " Mengganti Fungsi yang Lebih Lama dengan Modul subprocess " dalam dokumentasi subprocess mungkin memiliki beberapa resep yang bermanfaat.

3905
David Cournapeau

Berikut ini ringkasan cara memanggil program eksternal serta kelebihan dan kekurangan masing-masing:

  1. os.system("some_command with args") meneruskan perintah dan argumen ke Shell sistem Anda. Ini bagus karena Anda benar-benar dapat menjalankan banyak perintah sekaligus dengan cara ini dan mengatur pipa dan pengalihan input/output. Sebagai contoh: 

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

    Namun, sementara ini mudah, Anda harus secara manual menangani keluarnya karakter Shell seperti spasi, dll. Di sisi lain, ini juga memungkinkan Anda menjalankan perintah yang hanya perintah Shell dan bukan program eksternal sebenarnya. Lihat dokumentasi .

  2. stream = os.popen("some_command with args") akan melakukan hal yang sama seperti os.system kecuali itu memberi Anda objek seperti file yang dapat Anda gunakan untuk mengakses input/output standar untuk proses itu. Ada 3 varian popen lain yang semuanya menangani i/o sedikit berbeda. Jika Anda melewatkan semuanya sebagai string, maka perintah Anda akan diteruskan ke Shell; jika Anda melewati mereka sebagai daftar maka Anda tidak perlu khawatir akan melarikan diri apa pun. Lihat dokumentasi .

  3. Kelas Popen dari modul subprocess. Ini dimaksudkan sebagai pengganti os.popen tetapi memiliki kelemahan yang sedikit lebih rumit karena menjadi begitu komprehensif. Misalnya, Anda akan mengatakan:

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

    dari pada: 

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

    tapi itu bagus untuk memiliki semua opsi di sana dalam satu kelas terpadu, bukan 4 fungsi popen berbeda. Lihat dokumentasi .

  4. Fungsi call dari modul subprocess. Ini pada dasarnya sama seperti kelas Popen dan mengambil semua argumen yang sama, tetapi hanya menunggu sampai perintah selesai dan memberi Anda kode kembali. Sebagai contoh:

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

    Lihat dokumentasi .

  5. Jika Anda menggunakan Python 3.5 atau lebih baru, Anda dapat menggunakan fungsi subprocess.run yang baru, yang sangat mirip di atas tetapi bahkan lebih fleksibel dan mengembalikan objek CompletedProcess ketika perintah selesai dieksekusi.

  6. Modul os juga memiliki semua fungsi fork/exec/spawn yang Anda miliki dalam program C, tapi saya tidak merekomendasikan untuk menggunakannya secara langsung.

Modul subprocess mungkin seharusnya yang Anda gunakan.

Terakhir, perlu diketahui bahwa untuk semua metode di mana Anda melewati perintah terakhir yang akan dieksekusi oleh Shell sebagai string dan Anda bertanggung jawab untuk menghindarinya. Ada implikasi keamanan yang serius jika ada bagian dari string yang Anda lewati tidak dapat dipercaya sepenuhnya. Misalnya, jika pengguna memasukkan beberapa bagian string. Jika Anda tidak yakin, gunakan saja metode ini dengan konstanta. Untuk memberi Anda sedikit implikasi, pertimbangkan kode ini:

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

dan bayangkan pengguna memasukkan "ibuku tidak mencintaiku &&rm -rf /".

2665
Eli Courtwright

Saya biasanya menggunakan:

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()

Anda bebas melakukan apa yang Anda inginkan dengan data stdout di dalam pipa. Faktanya, Anda cukup menghilangkan parameter tersebut (stdout= dan stderr=) dan itu akan berperilaku seperti os.system().

292
EmmEff

Beberapa petunjuk tentang melepaskan proses anak dari proses pemanggilan (memulai proses anak di latar belakang).

Misalkan Anda ingin memulai tugas panjang dari skrip CGI, yaitu proses anak harus hidup lebih lama dari proses eksekusi skrip CGI.

Contoh klasik dari dokumen modul subproses adalah:

import subprocess
import sys

# some code here

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

# some more code here

Idenya di sini adalah bahwa Anda tidak ingin menunggu di baris 'panggilan subproses' sampai longtask.py selesai. Tetapi tidak jelas apa yang terjadi setelah baris 'kode lagi di sini' dari contoh.

Platform target saya adalah freebsd, tetapi pengembangannya ada di windows, jadi saya menghadapi masalah di windows terlebih dahulu.

Di windows (win xp), proses induk tidak akan selesai sampai longtask.py menyelesaikan pekerjaannya. Ini bukan yang Anda inginkan dalam skrip CGI. Masalahnya tidak spesifik untuk Python, di komunitas PHP masalahnya sama.

Solusinya adalah dengan melewati DETACHED_PROCESS Flag Pembuatan Proses ke fungsi CreateProcess yang mendasari dalam win API . Jika Anda menginstal pywin32 Anda dapat mengimpor flag dari modul win32process, jika tidak, Anda harus mendefinisikannya sendiri:

DETACHED_PROCESS = 0x00000008

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

/ * UPD 2015.10.27 @eryksun dalam komentar di bawah catatan, bahwa bendera yang benar secara semantik adalah CREATE_NEW_CONSOLE (0x00000010) * /

Pada freebsd kita memiliki masalah lain: ketika proses induk selesai, itu menyelesaikan proses anak juga. Dan itu juga bukan yang Anda inginkan dalam skrip CGI. Beberapa percobaan menunjukkan bahwa masalahnya sepertinya ada pada sharing sys.stdout. Dan solusi kerjanya adalah sebagai berikut:

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

Saya belum memeriksa kode di platform lain dan tidak tahu alasan perilaku di freebsd. Jika ada yang tahu, silakan bagikan ide Anda. Googling untuk memulai proses latar belakang dengan Python belum menjelaskan apa pun.

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

Jika Anda ingin mengembalikan hasil perintah, Anda dapat menggunakan os.popen . Namun, ini sudah tidak digunakan lagi sejak versi 2.6 mendukung modul subprocess , yang telah dijawab dengan baik oleh jawaban lain.

113
Alexandra Franks

Saya akan merekomendasikan menggunakan modul subproses daripada os.system karena Shell melarikan diri untuk Anda dan karenanya jauh lebih aman: http://docs.python.org/library/subprocess.html

subprocess.call(['ping', 'localhost'])
113
sirwart
import os
os.system("your command")

Perhatikan bahwa ini berbahaya, karena perintahnya tidak dibersihkan. Saya serahkan kepada Anda untuk google untuk dokumentasi yang relevan pada modul 'os' dan 'sys'. Ada banyak fungsi (exec * dan spawn *) yang akan melakukan hal serupa.

101
nimish

Ada banyak pustaka berbeda yang memungkinkan Anda untuk memanggil perintah eksternal dengan Python. Untuk setiap perpustakaan saya telah memberikan deskripsi dan menunjukkan contoh memanggil perintah eksternal. Perintah yang saya gunakan sebagai contoh adalah ls -l (daftar semua file). Jika Anda ingin mengetahui lebih lanjut tentang salah satu perpustakaan yang telah saya daftarkan dan menautkan dokumentasi untuk masing-masing perpustakaan.

Sumber:

Ini semua perpustakaan:

Semoga ini akan membantu Anda membuat keputusan tentang perpustakaan mana yang akan digunakan :)

subproses

Subprocess memungkinkan Anda untuk memanggil perintah eksternal dan menghubungkannya ke input/output/pipa kesalahan (stdin, stdout, dan stderr). Subprocess adalah pilihan default untuk menjalankan perintah, tetapi terkadang modul lain lebih baik.

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 digunakan untuk "fungsionalitas tergantung sistem operasi". Itu juga dapat digunakan untuk memanggil perintah eksternal dengan os.system dan os.popen (Catatan: Ada juga subprocess.popen). os akan selalu menjalankan Shell dan merupakan alternatif sederhana untuk orang yang tidak perlu, atau tidak tahu cara menggunakan subprocess.run.

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

SH

sh adalah antarmuka subproses yang memungkinkan Anda memanggil program seolah-olah itu adalah fungsi. Ini berguna jika Anda ingin menjalankan perintah beberapa kali.

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

timah hitam

plumbum adalah pustaka untuk program Python "mirip script". Anda dapat memanggil program seperti fungsi seperti dalam sh. Timah hitam berguna jika Anda ingin menjalankan pipa tanpa Shell.

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

harap daftar

pexpect memungkinkan Anda menelurkan aplikasi anak, mengontrolnya dan menemukan pola dalam hasilnya. Ini adalah alternatif yang lebih baik daripada subproses untuk perintah yang mengharapkan tty di Unix.

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

kain

fabric adalah pustaka Python 2.5 dan 2.7. Ini memungkinkan Anda untuk menjalankan perintah Shell lokal dan jarak jauh. Fabric adalah alternatif sederhana untuk menjalankan perintah di Shell yang aman (SSH)

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

utusan

utusan tersebut dikenal sebagai "subproses untuk manusia". Ini digunakan sebagai pembungkus kenyamanan di sekitar modul subprocess.

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

perintah

commands berisi fungsi wrapper untuk os.popen, tetapi telah dihapus dari Python 3 karena subprocess adalah alternatif yang lebih baik.

Hasil edit didasarkan pada komentar J.F. Sebastian.

63
Tom Fuller

Saya selalu menggunakan fabric untuk hal-hal ini seperti:

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

Tapi ini tampaknya menjadi alat yang bagus: sh (antarmuka subproses Python) .

Lihat sebuah contoh:

from sh import vgdisplay
print vgdisplay()
print vgdisplay('-v')
print vgdisplay(v=True)
60
Jorge E. Cardona

Periksa perpustakaan Python "pexpect" juga.

Ia memungkinkan untuk mengendalikan interaktif program/perintah eksternal, bahkan ssh, ftp, telnet, dll. Anda bisa mengetik sesuatu seperti:

child = pexpect.spawn('ftp 192.168.0.24')

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

child.sendline('anonymous')

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

Jika Anda memerlukan output dari perintah yang Anda panggil, Maka Anda dapat menggunakan 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'

Perhatikan juga parameter Shell .

Jika Shell True, perintah yang ditentukan akan dieksekusi melalui Shell. Ini dapat berguna jika Anda menggunakan Python terutama untuk meningkatkan aliran kontrol yang ditawarkannya pada sebagian besar sistem shell dan masih menginginkan akses mudah ke fitur Shell lainnya seperti pipa Shell, wildcard nama file, ekspansi variabel lingkungan, dan perluasan ~ ke rumah pengguna direktori. Namun, perhatikan bahwa Python sendiri menawarkan implementasi banyak fitur mirip Shell (khususnya, glob, fnmatch, os.walk(), os.path.expandvars(), os.path.expanduser(), dan shutil).

53
Facundo Casco

Dengan Perpustakaan Standar

Gunakan modul subproses (Python 3):

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

Ini adalah cara standar yang disarankan. Namun, tugas yang lebih rumit (pipa, keluaran, input, dll.) Dapat membosankan untuk dibangun dan ditulis.

Catatan pada versi Python: Jika Anda masih menggunakan Python 2, subprocess.call berfungsi dengan cara yang sama.

ProTip: shlex.split dapat membantu Anda menguraikan perintah untuk run, call, dan fungsi subprocess lainnya jika Anda tidak ingin (atau Anda tidak bisa!) Menyediakannya dalam bentuk daftar:

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

Dengan Ketergantungan Eksternal

Jika Anda tidak keberatan dengan ketergantungan eksternal, gunakan plumbum :

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

Ini adalah pembungkus subprocess terbaik. Ini lintas platform, mis. Berfungsi pada sistem Windows dan Unix. Instal dengan pip install plumbum.

Perpustakaan populer lainnya adalah sh :

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

Namun, sh menjatuhkan dukungan Windows, jadi tidak sehebat dulu. Instal dengan pip install sh.

51
Honza Javorek

Beginilah cara saya menjalankan perintah. Kode ini memiliki semua yang Anda butuhkan

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()
45
Usman Khan

Memperbarui:

subprocess.run adalah pendekatan yang disarankan pada Python 3.5 jika kode Anda tidak perlu mempertahankan kompatibilitas dengan versi Python sebelumnya. Ini lebih konsisten dan menawarkan kemudahan penggunaan yang sama seperti Utusan. (Perpipaan tidak sesederhana itu. Lihat pertanyaan ini untuk bagaimana .)

Berikut beberapa contoh dari dokumen .

Jalankan proses:

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

Naikkan saat gagal dijalankan:

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

Capture output:

>>> 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')

Jawaban asli:

Saya sarankan mencoba Utusan . Ini adalah pembungkus untuk subproses, yang pada gilirannya bertujuan untuk menggantikan modul dan fungsi yang lebih lama. Utusan adalah subproses bagi manusia.

Contoh penggunaan dari 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
''

Barang pipa sekitar juga:

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

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

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

Tanpa hasil keluaran:

import os
os.system("your command here")

Dengan output dari hasil:

import commands
commands.getoutput("your command here")
or
commands.getstatusoutput("your command here")
34
Zuckonit

https://docs.python.org/2/library/subprocess.html

... atau untuk perintah yang sangat sederhana:

import os
os.system('cat testfile')
28
Ben Hoffstein

Ada juga Timah hitam

>>> 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
27
stuckintheshuck

os.system OK, tapi agak ketinggalan zaman. Ini juga tidak terlalu aman. Sebagai gantinya, cobalah subprocess. subprocess tidak memanggil sh secara langsung dan karenanya lebih aman daripada os.system.

Dapatkan informasi lebih lanjut di sini .

27
Martin W

Memanggil perintah eksternal dengan Python

Sederhana, gunakan subprocess.run, yang mengembalikan objek 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)

Mengapa?

Pada Python 3.5, dokumentasi merekomendasikan subprocess.run :

Pendekatan yang disarankan untuk menjalankan subproses adalah menggunakan fungsi run () untuk semua kasus penggunaan yang dapat ditangani. Untuk kasus penggunaan yang lebih lanjut, antarmuka Popen yang mendasarinya dapat digunakan secara langsung.

Berikut adalah contoh penggunaan paling sederhana yang mungkin - dan tidak persis seperti yang diminta:

>>> 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 menunggu perintah berhasil diselesaikan, lalu mengembalikan objek CompletedProcess. Sebaliknya itu dapat meningkatkan TimeoutExpired (jika Anda memberikan argumen timeout=) atau CalledProcessError (jika gagal dan Anda meneruskan check=True).

Seperti yang dapat Anda simpulkan dari contoh di atas, stdout dan stderr keduanya disalurkan ke stdout dan stderr Anda secara default.

Kita dapat memeriksa objek yang dikembalikan dan melihat perintah yang diberikan dan kode pengembalian:

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

Menangkap output

Jika Anda ingin menangkap output, Anda dapat meneruskan subprocess.PIPE ke stderr atau stdout yang sesuai:

>>> 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''

(Saya menemukan ini menarik dan sedikit berlawanan dengan intuisi bahwa info versi dimasukkan ke stderr alih-alih stdout.)

Lulus daftar perintah

Seseorang mungkin dengan mudah berpindah dari memberikan string perintah secara manual (seperti yang disarankan pertanyaan) ke menyediakan string yang dibuat secara terprogram. Jangan membuat string secara pemrograman. Ini adalah masalah keamanan potensial. Lebih baik untuk menganggap Anda tidak percaya input. 

>>> 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'

Catatan, hanya args yang harus dilewati secara posisi.

Tanda tangan penuh

Inilah tanda tangan aktual di sumber dan seperti yang ditunjukkan oleh help(run):

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

popenargs dan kwargs diberikan kepada konstruktor Popen. input dapat berupa string byte (atau unicode, jika ditentukan penyandian atau universal_newlines=True) yang akan disalurkan ke stdin subproses.

Dokumentasi menjelaskan timeout= dan check=True lebih baik daripada yang saya bisa:

Argumen batas waktu diteruskan ke Popen.communicate (). Jika batas waktu berakhir, proses anak akan dibunuh dan menunggu. Itu Pengecualian TimeoutExpired akan dimunculkan kembali setelah proses anak memiliki dihentikan.

Jika check benar, dan proses keluar dengan kode keluar yang tidak nol, a Pengecualian CalledProcessError akan dimunculkan. Atribut itu pengecualian memegang argumen, kode keluar, dan stdout dan stderr jika mereka ditangkap.

dan contoh ini untuk check=True lebih baik daripada yang saya bisa dapatkan:

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

Tanda Tangan yang Diperluas

Berikut tanda tangan yang diperluas, seperti yang diberikan dalam dokumentasi:

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

Perhatikan bahwa ini menunjukkan bahwa hanya daftar args yang harus dilewati secara posisi. Jadi berikan argumen yang tersisa sebagai argumen kata kunci.

Popen

Kapan menggunakan Popen sebagai gantinya? Saya akan berjuang untuk menemukan use case berdasarkan argumen saja. Namun, penggunaan langsung Popen akan memberi Anda akses ke metode-metodenya, termasuk poll, 'send_signal', 'terminate', dan 'wait'.

Inilah tanda tangan Popen seperti yang diberikan pada sumber . Saya pikir ini adalah enkapsulasi informasi yang paling tepat (berbeda dengan 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):

Tetapi yang lebih informatif adalah dokumentasi Popen :

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)

Jalankan program anak dalam proses baru. Pada POSIX, kelas menggunakan os.execvp () - perilaku seperti untuk menjalankan program anak. Di Windows, kelas menggunakan fungsi Windows CreateProcess (). Argumen untuk Popen adalah sebagai berikut.

Memahami dokumentasi yang tersisa pada Popen akan dibiarkan sebagai latihan untuk pembaca.

24
Aaron Hall

Ini bisa sesederhana ini:

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

Menggunakan:

import os

cmd = 'ls -al'

os.system(cmd)

os - Modul ini menyediakan cara portabel menggunakan fungsionalitas yang tergantung pada sistem operasi.

Untuk fungsi yang lebih os, di sini adalah dokumentasi.

23
Priyankara

subprocess.check_call nyaman jika Anda tidak ingin menguji nilai pengembalian. Itu melempar pengecualian pada kesalahan apa pun.

19
cdunn2001

Saya cenderung menggunakan subproses bersama dengan shlex (untuk menangani pelolosan string yang dikutip):

>>> 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)
18
Emil Stenström

os.system tidak memungkinkan Anda menyimpan hasil, jadi jika Anda ingin menyimpan hasil dalam beberapa daftar atau sesuatu subprocess.call berfungsi.

17
Saurabh Bangad

Ada perbedaan lain di sini yang tidak disebutkan sebelumnya.

subprocess.Popen mengeksekusi <command> sebagai subproses. Dalam kasus saya, saya perlu menjalankan file <a> yang perlu berkomunikasi dengan program lain, <b>. 

Saya mencoba subproses, dan eksekusi berhasil. Namun <b> tidak dapat berkomunikasi dengan <a> . Semuanya normal ketika saya menjalankan keduanya dari terminal.

Satu lagi: (CATATAN: kwrite berperilaku berbeda dari aplikasi lain. Jika Anda mencoba yang di bawah ini dengan Firefox, hasilnya tidak akan sama.)

Jika Anda mencoba os.system("kwrite"), aliran program membeku hingga pengguna menutup kwrite. Untuk mengatasinya saya malah mencoba os.system(konsole -e kwrite). Program waktu ini terus mengalir, tetapi kwrite menjadi subproses konsol.

Siapa pun yang menjalankan kwrite bukan menjadi subproses (mis. Di monitor sistem, kwrite harus muncul di Edge paling kiri dari tree).

17
Atinc Delican

Saya sangat suka Shell_command untuk kesederhanaannya. Itu dibangun di atas modul subproses.

Berikut ini contoh dari dokumen:

>>> 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
16
mdwhatcott

gunakan modul os

import os
os.system("your command")

misalnya

import os
os.system("ifconfig")
15
abhi krishnan

Shameless plug, saya menulis sebuah perpustakaan untuk ini: P https://github.com/houqp/Shell.py

Ini pada dasarnya pembungkus popen dan shlex untuk saat ini. Ini juga mendukung perintah perpipaan sehingga Anda dapat melakukan perintah dengan lebih mudah dengan Python. Jadi Anda bisa melakukan hal-hal seperti:

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

Di Linux, jika Anda ingin memanggil perintah eksternal yang akan dieksekusi secara independen (akan tetap berjalan setelah skrip python berakhir), Anda dapat menggunakan antrian sederhana sebagai task spooler atau perintah at

Contoh dengan pengumpul tugas:

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

Catatan tentang spooler tugas (ts): 

  1. Anda bisa mengatur jumlah proses bersamaan untuk dijalankan ("slot") dengan:

    ts -S <number-of-slots>

  2. Instalasi ts tidak memerlukan hak admin. Anda dapat mengunduh dan mengompilasinya dari sumber dengan make sederhana, menambahkannya ke jalur Anda dan selesai.

14
Yuval Atzmon

Anda dapat menggunakan Popen, dan kemudian Anda dapat memeriksa status prosedur:

from subprocess import Popen

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

Lihat subproses.Popen .

13
admire

Di Windows, Anda cukup mengimpor modul subprocess dan menjalankan perintah eksternal dengan memanggil subprocess.Popen(), subprocess.Popen().communicate() dan subprocess.Popen().wait() seperti di bawah ini:

# 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)

Keluaran:

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

Cara paling sederhana untuk menjalankan perintah apa pun dan mendapatkan hasilnya kembali:

from commands import getstatusoutput

try:
    return getstatusoutput("ls -ltr")
except Exception, e:
    return None
11
Garfield

Untuk mengambil id jaringan dari neutron openstack:

#!/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)

Output dari daftar net nova

+--------------------------------------+------------+------+
| 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 |
+--------------------------------------+------------+------+

Output dari print (networkId)

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

Inilah dua sen saya: Dalam pandangan saya, ini adalah praktik terbaik ketika berhadapan dengan perintah eksternal ...

Ini adalah nilai kembali dari metode eksekusi ...

pass, stdout, stderr = execute(["ls","-la"],"/home/user/desktop")

Ini adalah metode eksekusi ...

def execute(cmdArray,workingDir):

    stdout = ''
    stderr = ''

    try:
        try:
            process = subprocess.Popen(cmdArray,cwd=workingDir, stdout=subprocess.PIPE, stderr=subprocess.PIPE, bufsize=1)
        except OSError:
            return [False, '', 'ERROR : command(' + ' '.join(cmdArray) + ') could not get executed!']

        for line in iter(process.stdout.readline, b''):

            try:
                echoLine = line.decode("utf-8")
            except:
                echoLine = str(line)

            stdout += echoLine

        for line in iter(process.stderr.readline, b''):

            try:
                echoLine = line.decode("utf-8")
            except:
                echoLine = str(line)

            stderr += echoLine

    except (KeyboardInterrupt,SystemExit) as err:
        return [False,'',str(err)]

    process.stdout.close()

    returnCode = process.wait()
    if returnCode != 0 or stderr != '':
        return [False, stdout, stderr]
    else:
        return [True, stdout, stderr]
10
Uroš Jarc

Invoke adalah alat & pustaka pelaksanaan tugas Python (2.7 dan 3.4+). Ini menyediakan API tingkat tinggi yang bersih untuk menjalankan perintah Shell

>>> from invoke import run
>>> cmd = "pip install -r requirements.txt"
>>> result = run(cmd, hide=True, warn=True)
>>> print(result.ok)
True
>>> print(result.stdout.splitlines()[-1])
Successfully installed invocations-0.13.0 pep8-1.5.7 spec-1.3.1
8
Valery Ramusik

Di sini memanggil perintah eksternal dan mengembalikan atau mencetak output perintah:

Python Subprocess check_output bagus untuk

Jalankan perintah dengan argumen dan kembalikan hasilnya sebagai string byte.

import subprocess
proc = subprocess.check_output('ipconfig /all')
print proc
7
Rajiv Sharma

Menggunakan:

import subprocess

p = subprocess.Popen("df -h", Shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0]
print p.split("\n")

Ini memberikan hasil yang bagus yang lebih mudah untuk dikerjakan:

['Filesystem      Size  Used Avail Use% Mounted on',
 '/dev/sda6        32G   21G   11G  67% /',
 'none            4.0K     0  4.0K   0% /sys/fs/cgroup',
 'udev            1.9G  4.0K  1.9G   1% /dev',
 'tmpfs           387M  1.4M  386M   1% /run',
 'none            5.0M     0  5.0M   0% /run/lock',
 'none            1.9G   58M  1.9G   3% /run/shm',
 'none            100M   32K  100M   1% /run/user',
 '/dev/sda5       340G  222G  100G  69% /home',
 '']
7
David Okwii

Hanya untuk menambah diskusi, jika Anda termasuk menggunakan konsol Python, Anda dapat memanggil perintah eksternal dari IPython . Saat berada di IPython Prompt, Anda dapat memanggil perintah Shell dengan mengawali '!'. Anda juga dapat menggabungkan kode Python dengan Shell, dan menetapkan output skrip Shell ke variabel Python.

Contohnya:

In [9]: mylist = !ls

In [10]: mylist
Out[10]:
['file1',
 'file2',
 'file3',]
7
imagineerThat

Memanggil perintah eksternal dengan Python

Cara sederhana untuk memanggil perintah eksternal menggunakan os.system(...). Dan fungsi ini mengembalikan nilai keluar dari perintah. Namun kekurangannya adalah kita tidak akan mendapatkan stdout dan stderr.

ret = os.system('some_cmd.sh')
if ret != 0 :
    print 'some_cmd.sh execution returned failure'

Memanggil perintah eksternal dengan Python di latar belakang

subprocess.Popen memberikan lebih banyak fleksibilitas untuk menjalankan perintah eksternal daripada menggunakan os.system. Kita dapat memulai perintah di latar belakang dan menunggu sampai selesai. Dan setelah itu kita bisa mendapatkan stdout dan stderr.

proc = subprocess.Popen(["./some_cmd.sh"], stdout=subprocess.PIPE)
print 'waiting for ' + str(proc.pid)
proc.wait()
print 'some_cmd.sh execution finished'
(out, err) = proc.communicate()
print 'some_cmd.sh output : ' + out

Memanggil perintah eksternal yang berjalan lama dengan Python di latar belakang dan berhenti setelah beberapa waktu

Kita bahkan dapat memulai proses yang berjalan lama di latar belakang menggunakan subprocess.Popen dan membunuhnya setelah beberapa saat setelah tugasnya selesai.

proc = subprocess.Popen(["./some_long_run_cmd.sh"], stdout=subprocess.PIPE)
# Do something else
# Now some_long_run_cmd.sh exeuction is no longer needed, so kill it
os.system('kill -15 ' + str(proc.pid))
print 'Output : ' proc.communicate()[0]
6
rashok

Ada banyak cara berbeda untuk menjalankan perintah eksternal dengan Python, Dan semuanya memiliki kelebihan dan kekurangannya masing-masing.

Rekan-rekan saya dan saya telah menulis alat administrasi sistem Python, jadi kita perlu menjalankan banyak perintah eksternal, dan kadang-kadang Anda ingin mereka memblokir atau menjalankan secara tidak sinkron, waktu habis, perbarui setiap detik, dll.

Ada juga berbagai cara penanganan kode pengembalian dan kesalahan, Dan Anda mungkin ingin mem-parsing output, dan memberikan input baru (dalam gaya mengharapkan jenis). Atau Anda harus mengarahkan ulang stdin, stdout, dan stderr untuk berjalan di tty yang berbeda (mis., Saat menggunakan layar).

Jadi Anda mungkin harus menulis banyak pembungkus di sekitar perintah eksternal. Jadi di sini adalah modul Python yang telah kami tulis yang dapat menangani hampir semua yang Anda inginkan, dan jika tidak, modul ini sangat fleksibel sehingga Anda dapat dengan mudah memperluasnya:

https://github.com/hpcugent/vsc-base/blob/master/lib/vsc/utils/run.py

6
Jens Timmerman

Sebagai contoh (di Linux):

import subprocess
subprocess.run('mkdir test.dir', Shell=True)

Ini menciptakan test.dir di direktori saat ini . Perhatikan bahwa ini juga berfungsi:

import subprocess
subprocess.call('mkdir test.dir', Shell=True)

Kode yang setara menggunakan os.system adalah:

import os
os.system('mkdir test.dir')

Praktik terbaik adalah menggunakan subproses alih-alih os, dengan .run lebih disukai daripada .call. Yang perlu Anda ketahui tentang subproses adalah sini . Juga, perhatikan bahwa semua dokumentasi Python tersedia untuk diunduh dari sini . Saya mengunduh PDF yang dikemas sebagai .Zip. Saya menyebutkan ini karena ada ikhtisar Nice dari modul os di tutorial.pdf (halaman 81). Selain itu, ini merupakan sumber daya otoritatif untuk coders Python.

6
user8468899

Untuk Python 3.5+ disarankan agar Anda menggunakan fungsi run dari modul subprocess . Ini mengembalikan objek CompletedProcess, dari mana Anda dapat dengan mudah mendapatkan output serta kode kembali.

from subprocess import PIPE, run

command = ['echo', 'hello']
result = run(command, stdout=PIPE, stderr=PIPE, universal_newlines=True)
print(result.returncode, result.stdout, result.stderr)
5
Chiel ten Brinke

Seringkali, saya menggunakan fungsi berikut untuk perintah eksternal, dan ini sangat berguna untuk proses yang berjalan lama . Metode di bawah membuntuti keluaran proses ketika sedang berjalan dan mengembalikan keluaran, menimbulkan pengecualian jika proses gagal.

Keluar jika proses dilakukan menggunakan metode poll () pada proses .

import subprocess,sys

def exec_long_running_proc(command, args):
    cmd = "{} {}".format(command, " ".join(str(arg) if ' ' not in arg else arg.replace(' ','\ ') for arg in args))
    print(cmd)
    process = subprocess.Popen(cmd, Shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

    # Poll process for new output until finished
    while True:
        nextline = process.stdout.readline().decode('UTF-8')
        if nextline == '' and process.poll() is not None:
            break
        sys.stdout.write(nextline)
        sys.stdout.flush()

    output = process.communicate()[0]
    exitCode = process.returncode

    if (exitCode == 0):
        return output
    else:
        raise Exception(command, exitCode, output)

Anda bisa memanggilnya seperti ini:

exec_long_running_proc(command = "Hive", args=["-f", hql_path])
5
am5

Cara sederhana adalah dengan menggunakan modul os:

import os
os.system('ls')

Atau Anda juga dapat menggunakan modul subproses

import subprocess
subprocess.check_call('ls')

Jika Anda ingin hasilnya disimpan dalam variabel, coba:

import subprocess
r = subprocess.check_output('ls')
4
amehta

Gunakan subprocess.call :

from subprocess import call

# using list
call(["echo", "Hello", "world"])

# single string argument varies across platforms so better split it
call("echo Hello world".split(" "))
4
andruso

Menggunakan fungsi Popen dari modul Python subprocess adalah cara paling sederhana untuk menjalankan perintah Linux. Dalam hal itu, fungsi Popen.communicate() akan memberikan output perintah Anda. Sebagai contoh

import subprocess

..
process = subprocess.Popen(..)   # Pass command and arguments to the function
stdout, stderr = process.communicate()   # Get command output and error
..
4
Asif Hasnain

Ada banyak cara untuk memanggil perintah.

  • Sebagai contoh:

jika and.exe membutuhkan dua parameter. Dalam cmd kita bisa memanggil sample.exe gunakan ini: and.exe 2 3 dan itu menunjukkan 5 di layar.

Jika kita menggunakan skrip Python untuk memanggil and.exe, kita harus melakukannya seperti ..

  1. os.system(cmd,...)

    • os.system(("and.exe" + " " + "2" + " " + "3"))
  2. os.popen(cmd,...)

    • os.popen(("and.exe" + " " + "2" + " " + "3"))
  3. subprocess.Popen(cmd,...)
    • subprocess.Popen(("and.exe" + " " + "2" + " " + "3"))

Ini terlalu sulit, jadi kita bisa bergabung dengan cmd dengan spasi:

import os
cmd = " ".join(exename,parameters)
os.popen(cmd)
4
liuyip

Jika Anda perlu memanggil perintah Shell dari notebook Python (seperti Jupyter , Zeppelin, Databricks, atau Google Cloud Datalab) Anda bisa menggunakan awalan !.

Sebagai contoh,

!ls -ilF
3
dportman

Saya menulis perpustakaan kecil untuk membantu dengan use case ini:

https://pypi.org/project/citizenshell/

Itu dapat diinstal menggunakan 

pip install citizenshell

Dan kemudian digunakan sebagai berikut:

from citizenshell import sh
assert sh("echo Hello World") == "Hello World"

Anda dapat memisahkan stdout dari stderr dan mengekstrak kode keluar sebagai berikut:

result = sh(">&2 echo error && echo output && exit 13")
assert result.stdout() == ["output"]
assert result.stderr() == ["error"]
assert result.exit_code() == 13

Dan hal yang keren adalah Anda tidak perlu menunggu Shell yang mendasari untuk keluar sebelum mulai memproses output:

for line in sh("for i in 1 2 3 4; do echo -n 'It is '; date +%H:%M:%S; sleep 1; done", wait=False)
    print ">>>", line + "!"

akan mencetak garis karena tersedia berkat menunggu = Salah

>>> It is 14:24:52!
>>> It is 14:24:53!
>>> It is 14:24:54!
>>> It is 14:24:55!

Contoh lebih lanjut dapat ditemukan di https://github.com/meuter/citizenshell

3
Cédric

Ada dua cara yang menonjol di mana seseorang dapat menjalankan perintah Shell menggunakan Python. Kedua contoh yang disebutkan di bawah menunjukkan bagaimana seseorang bisa mendapatkan nama direktori kerja saat ini (pwd) menggunakan Python. Anda dapat menggunakan perintah Unix lainnya sebagai ganti pwd

1.> Metode 1: Seseorang dapat menggunakan modul os dari python, dan system () berfungsi dari sana untuk menjalankan perintah Shell dengan Python.

import os
os.system('pwd')

Keluaran:

/Users/siddharth

1.> Metode ke-2: Cara lain adalah dengan menggunakan subprocess module dan call () function. 

import subprocess
subprocess.call('pwd')

Keluaran:

/Users/siddharth
3

Saya akan merekomendasikan metode 'run' berikut dan ini akan membantu kami dalam mendapatkan STDOUT, STDERR, dan keluar dari status sebagai kamus; Penelepon ini dapat membaca kamus kembali dengan metode 'run' untuk mengetahui keadaan proses yang sebenarnya. 

  def run (cmd):
       print "+ DEBUG exec({0})".format(cmd)
       p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, Shell=True)
       (out, err) = p.communicate()
       ret        = p.wait()
       out        = filter(None, out.split('\n'))
       err        = filter(None, err.split('\n'))
       ret        = True if ret == 0 else False
       return dict({'output': out, 'error': err, 'status': ret})
  #end
2
Viswesn

Setelah beberapa penelitian, saya memiliki kode berikut yang bekerja sangat baik untuk saya. Ini pada dasarnya mencetak stdout dan stderr secara real time. Semoga ini bisa membantu orang lain yang membutuhkannya.

stdout_result = 1
stderr_result = 1


def stdout_thread(pipe):
    global stdout_result
    while True:
        out = pipe.stdout.read(1)
        stdout_result = pipe.poll()
        if out == '' and stdout_result is not None:
            break

        if out != '':
            sys.stdout.write(out)
            sys.stdout.flush()


def stderr_thread(pipe):
    global stderr_result
    while True:
        err = pipe.stderr.read(1)
        stderr_result = pipe.poll()
        if err == '' and stderr_result is not None:
            break

        if err != '':
            sys.stdout.write(err)
            sys.stdout.flush()


def exec_command(command, cwd=None):
    if cwd is not None:
        print '[' + ' '.join(command) + '] in ' + cwd
    else:
        print '[' + ' '.join(command) + ']'

    p = subprocess.Popen(
        command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd
    )

    out_thread = threading.Thread(name='stdout_thread', target=stdout_thread, args=(p,))
    err_thread = threading.Thread(name='stderr_thread', target=stderr_thread, args=(p,))

    err_thread.start()
    out_thread.start()

    out_thread.join()
    err_thread.join()

    return stdout_result + stderr_result
2
Jake W

Saya telah menulis pembungkus untuk menangani kesalahan dan mengarahkan output dan hal-hal lain.

import shlex
import psutil
import subprocess

def call_cmd(cmd, stdout=sys.stdout, quiet=False, Shell=False, raise_exceptions=True, use_shlex=True, timeout=None):
    """Exec command by command line like 'ln -ls "/var/log"'
    """
    if not quiet:
        print("Run %s", str(cmd))
    if use_shlex and isinstance(cmd, (str, unicode)):
        cmd = shlex.split(cmd)
    if timeout is None:
        process = subprocess.Popen(cmd, stdout=stdout, stderr=sys.stderr, Shell=shell)
        retcode = process.wait()
    else:
        process = subprocess.Popen(cmd, stdout=stdout, stderr=sys.stderr, Shell=shell)
        p = psutil.Process(process.pid)
        finish, alive = psutil.wait_procs([p], timeout)
        if len(alive) > 0:
            ps = p.children()
            ps.insert(0, p)
            print('waiting for timeout again due to child process check')
            finish, alive = psutil.wait_procs(ps, 0)
        if len(alive) > 0:
            print('process {} will be killed'.format([p.pid for p in alive]))
            for p in alive:
                p.kill()
            if raise_exceptions:
                print('External program timeout at {} {}'.format(timeout, cmd))
                raise CalledProcessTimeout(1, cmd)
        retcode = process.wait()
    if retcode and raise_exceptions:
        print("External program failed %s", str(cmd))
        raise subprocess.CalledProcessError(retcode, cmd)

Anda bisa menyebutnya seperti ini:

cmd = 'ln -ls "/var/log"'
stdout = 'out.txt'
call_cmd(cmd, stdout)
1
Asav Patel

Modul subprocess yang dijelaskan di atas oleh Eli sangat kuat, tetapi sintaks untuk membuat panggilan sistem standar-rawa dan memeriksa hasilnya, tidak perlu prolix.

Cara termudah untuk melakukan panggilan sistem adalah dengan modul commands (hanya Linux).

> import commands
> commands.getstatusoutput("grep matter alice-in-wonderland.txt")
(0, "'Then it doesn't matter which way you go,' said the Cat.")

Item pertama dalam Tuple adalah kode pengembalian proses. Item kedua adalah output standarnya (dan standard error, digabung).


Para pengembang Python telah 'mencabut' modul perintah, tetapi itu tidak berarti Anda tidak boleh menggunakannya. Hanya saja mereka tidak mengembangkannya lagi, yang tidak apa-apa, karena sudah sempurna (pada fungsi kecil tapi penting).

1
Colonel Panic

Karena beberapa jawaban terkait dengan versi python sebelumnya atau menggunakan modul os.system saya memposting jawaban ini untuk orang-orang seperti saya yang berniat untuk menggunakan subprocess di python 3.5+. Berikut ini trik untuk saya di Linux:

import subprocess

#subprocess.run() returns a completed process object that can be inspected
c = subprocess.run(["ls", "-ltrh"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
print(c.stdout.decode('utf-8'))

Seperti yang disebutkan dalam dokumentasi , nilai-nilai PIPE adalah urutan byte dan untuk menunjukkannya dengan benar, decoding harus dipertimbangkan. Untuk versi python yang lebih baru, text=True dan encoding='utf-8' ditambahkan ke kwargs dari subprocess.run()

Output dari kode di atas adalah:

total 113M
-rwxr-xr-x  1 farzad farzad  307 Jan 15  2018 vpnscript
-rwxrwxr-x  1 farzad farzad  204 Jan 15  2018 ex
drwxrwxr-x  4 farzad farzad 4.0K Jan 22  2018 scripts
.... # some other lines
1
Farzad Vertigo

Jika AndaTIDAKmenggunakan input pengguna dalam perintah, Anda dapat menggunakan ini

from os import getcwd
from subprocess import check_output
from shlex import quote

def sh(command):
    return check_output(quote(command), Shell=True, cwd=getcwd(), universal_newlines=True).strip()

Dan gunakan sebagai

branch = sh('git rev-parse --abbrev-ref HEAD') 

Shell=True akan menelurkan Shell, sehingga Anda dapat menggunakan pipa dan hal-hal Shell semacam itu sh('ps aux | grep python'). Ini sangat berguna untuk menjalankan perintah hardcoded dan memproses outputnya. universal_lines=True memastikan output dikembalikan dalam string, bukan biner.

cwd=getcwd() akan memastikan bahwa perintah dijalankan dengan direktori kerja yang sama dengan interpreter. Ini berguna untuk perintah git agar berfungsi seperti contoh nama cabang git di atas.

Beberapa resep

  • bebaskan memori dalam megabita: sh('free -m').split('\n')[1].split()[1]
  • ruang kosong di/dalam persen sh('df -m /').split('\n')[1].split()[4][0:-1]
  • cpu memuat sum(map(float, sh('ps -ef -o pcpu').split('\n')[1:])

Tetapi ini tidak aman untuk input pengguna, dari dokumen:

Pertimbangan Keamanan¶

Tidak seperti beberapa fungsi popen lainnya, implementasi ini tidak akan pernah secara implisit memanggil sistem Shell. Ini berarti bahwa semua karakter, termasuk karakter meta Shell, dapat dengan aman diteruskan ke proses anak. Jika Shell dipanggil secara eksplisit, melalui Shell = True, itu adalah tanggung jawab aplikasi untuk memastikan bahwa semua spasi dan metakarakter dikutip dengan tepat untuk menghindari kerentanan injeksi Shell.

Saat menggunakan Shell = True, fungsi shlex.quote () dapat digunakan untuk keluar dengan benar dari spasi putih dan metakarakter Shell dalam string yang akan digunakan untuk membuat perintah Shell.

Bahkan menggunakan shlex.quote() adalah baik untuk menjaga sedikit paranoid saat menggunakan input pengguna pada perintah Shell. Salah satu opsi adalah menggunakan perintah hardcode untuk mengambil beberapa keluaran umum dan memfilter berdasarkan input pengguna. Bagaimanapun menggunakan Shell=False akan memastikan bahwa hanya proses yang ingin Anda jalankan yang akan dieksekusi atau Anda mendapatkan kesalahan No such file or directory.

Juga ada beberapa dampak kinerja pada Shell=True, dari pengujian saya tampaknya sekitar 20% lebih lambat dari Shell=False (default).

In [50]: timeit("check_output('ls -l'.split(), universal_newlines=True)", number=1000, globals=globals())
Out[50]: 2.6801227919995654

In [51]: timeit("check_output('ls -l', universal_newlines=True, Shell=True)", number=1000, globals=globals())
Out[51]: 3.243950183999914
0
geckos