Bir Python betiğinden harici bir komutu (Unix Shell veya Windows komut istemine yazmışım gibi) nasıl çağırabilirim?
Standart kütüphanedeki alt işlem modülü 'ye bakın:
import subprocess
subprocess.run(["ls", "-l"])
Subprocess vs. system 'in avantajı, daha esnek olmasıdır (stdout, stderr, "gerçek" durum kodu, daha iyi hata yönetimi vb. ...).
Resmi evraklarsubprocess modülünü alternatif os.system () üzerinden önerir:
Subprocess modülü, yeni işlemlerin yapılması ve sonuçlarının alınması için daha güçlü olanaklar sağlar; bu modülü kullanmak bu işlevi kullanmak için tercih edilir [
os.system()
].
" Eski İşlevleri subprocess belgelerinde alt işlem Modülü " bölümüyle değiştirmek bazı yararlı tariflere sahip olabilir.
İşte harici programları çağırmanın yollarını ve her birinin avantaj ve dezavantajlarını özetleyen:
os.system("some_command with args")
komutu ve argümanları sisteminizin Kabuğuna iletir. Bu Güzel, çünkü bir kerede birden fazla komutu bu şekilde çalıştırabilir, boru ve giriş/çıkış yönlendirmesini ayarlayabilirsiniz. Örneğin:
os.system("some_command < input_file | another_command > output_file")
Bununla birlikte, bu elverişli olsa da, boşluklar vb. Gibi Shell karakterlerinden kaçışınızı manüel olarak ele almanız gerekir. Öte yandan, bu aynı zamanda sadece harici komutlar değil, sadece Shell komutları olan komutları çalıştırmanıza izin verir. Bkz. Belgeler .
stream = os.popen("some_command with args")
, bu işlem için standart giriş/çıkışa erişmek için kullanabileceğiniz dosyaya benzer bir nesne vermesi dışında os.system
ile aynı şeyi yapar. Hepsi G/Ç'yi biraz farklı şekilde ele alan 3 popen varyantı daha vardır. Her şeyi bir dize olarak iletirseniz, komutunuz Kabuk'a iletilir; Onları bir liste halinde geçirirseniz, hiçbir şeyden kaçma konusunda endişelenmenize gerek kalmaz. Bkz. Belgeler .
Popen
modülünün subprocess
sınıfı. Bu os.popen
yerine geçecek şekilde tasarlanmıştır, ancak çok kapsamlı olması nedeniyle biraz daha karmaşık olmanın dezavantajı vardır. Örneğin, şöyle diyeceksiniz:
print subprocess.Popen("echo Hello World", Shell=True, stdout=subprocess.PIPE).stdout.read()
yerine:
print os.popen("echo Hello World").read()
ancak 4 farklı popen işlevi yerine, tüm seçeneklerin birleşik bir sınıfta olması güzel. Bkz. Belgeler .
call
işlevi, subprocess
modülünden. Bu temelde Popen
sınıfına benzer ve aynı argümanların hepsini alır, ancak komut tamamlanana ve size dönüş kodunu verene kadar bekler. Örneğin:
return_code = subprocess.call("echo Hello World", Shell=True)
Bkz. Belgeler .
Python 3.5 veya daha yenisindeyseniz, yukarıdaki gibi olan ancak daha da esnek olan yeni (subprocess.run
işlevini kullanabilirsiniz ve komut tamamlandığında CompletedProcess
nesnesini döndürürsünüz yürütülmesi.
Os modülü aynı zamanda bir C programında sahip olabileceğiniz tüm çatal/exec/spawn işlevlerine de sahiptir, ancak bunları doğrudan kullanmanızı önermiyorum.
subprocess
modülü muhtemelen kullandığınız şey olmalıdır.
Son olarak, Shell tarafından bir dizge olarak yürütülecek son komutu geçtiğiniz tüm yöntemlerde ve ondan kaçmaktan sorumlu olduğunuzu lütfen unutmayın. İlettiğiniz dizenin herhangi bir kısmına tamamen güvenilemiyorsa, ciddi güvenlik sonuçları vardır. Örneğin, bir kullanıcı dizenin bir kısmını/herhangi bir kısmını giriyorsa. Emin değilseniz, bu metodları sadece sabitler ile kullanın. Size bir ipucu vermek için bu kodu göz önünde bulundurun:
print subprocess.Popen("echo %s " % user_input, stdout=PIPE).stdout.read()
ve kullanıcının "annemin beni sevmediğini & & rm -rf /" girdiğini hayal edin.
Genelde kullanırım:
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()
Boruda stdout
verileriyle istediğinizi yapmakta özgürsünüz. Aslında, bu parametreleri atlayabilirsiniz (stdout=
ve stderr=
) ve os.system()
gibi davranır.
Çocuk sürecini çağıran işlemden ayırma konusunda bazı ipuçları (çocuk işlemine arka planda başlama).
Bir CGI betiğinden uzun bir görev başlatmak istediğinizi varsayalım; bu, alt işlemin CGI betiği yürütme işleminden daha uzun yaşaması gerektiğidir.
Alt işlem modülü dokümanlarından klasik örnek:
import subprocess
import sys
# some code here
pid = subprocess.Popen([sys.executable, "longtask.py"]) # call subprocess
# some more code here
Buradaki fikir, longtask.py bitinceye kadar 'subprocess çağrısı' satırında beklemek istemeyeceğinizdir. Ancak örnekten 'burada biraz daha kod' satırından sonra ne olduğu açık değildir.
Hedef platformum freebsd idi, ancak geliştirme pencerelerde yapıldı, bu yüzden ilk önce pencerelerde sorunla karşılaştım.
Pencerelerde (win xp), longtask.py çalışmasını bitirinceye kadar ana işlem bitmez. CGI-betiğinde istediğin bu değil. Sorun Python'a özgü değil, PHP topluluğunda problemler aynı.
Çözüm, DETACHED_PROCESS İşlem Oluşturma Bayrağı 'nın win API'sindeki temel CreateProcess işlevine geçmesidir. • pywin32'yi kurduysanız, bayrağı win32process modülünden içe aktarabilirsiniz;
DETACHED_PROCESS = 0x00000008
pid = subprocess.Popen([sys.executable, "longtask.py"],
creationflags=DETACHED_PROCESS).pid
/ * UPD 2015.10.27 @eryksun, aşağıdaki açıklamada, anlamsal olarak doğru bayrağın CREATE_NEW_CONSOLE (0x00000010) */olduğunu not eder.
Freebsd'de başka bir sorunumuz var: ebeveyn işlemi bittiğinde, çocuk işlemlerini de bitirir. Ve CGI-betiğinde de istediğin bu değil. Bazı deneyler, sorunun sys.stdout paylaşımında göründüğünü göstermiştir. Ve çalışma çözümü şuydu:
pid = subprocess.Popen([sys.executable, "longtask.py"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
Kodu diğer platformlarda kontrol etmedim ve freebsd'deki davranışın nedenlerini bilmiyorum. Eğer biri biliyorsa, lütfen fikirlerinizi paylaşın. Python'da arkaplan işlemlerinin başlatılması üzerine googling henüz bir ışık tutmuyor.
import os
cmd = 'ls -al'
os.system(cmd)
Komutun sonuçlarını döndürmek istiyorsanız, os.popen
komutunu kullanabilirsiniz. Bununla birlikte, 2.6 sürümünden bu yana, diğer cevapların iyi ele aldığı subprocess module 'nın lehine kaldırılmıştır.
Os.system yerine subprocess modülünü kullanmanızı öneririm, çünkü Shell sizin için kaçıyor ve bu yüzden daha güvenli: http://docs.python.org/library/subprocess.html
subprocess.call(['ping', 'localhost'])
import os
os.system("your command")
Komutun temizlenmediğinden tehlikeli olduğunu unutmayın. 'Os' ve 'sys' modülleriyle ilgili dokümantasyon için Google'ı size bırakıyorum. Benzer şeyler yapacak birçok fonksiyon (exec * ve spawn *) vardır.
Python ile harici komutları çağırmanıza izin veren birçok kitaplık vardır. Her kütüphane için bir tanım verdim ve harici bir komut çağırmanın bir örneğini gösterdim. Örnek olarak kullandığım komut ls -l
(bütün dosyaları listele). Kütüphanelerden herhangi biri hakkında daha fazla bilgi edinmek istiyorsanız listelediklerim ve her biri için dokümantasyonu bağladım.
Kaynaklar:
Bunlar kütüphanelerin tümü:
Umarım bu, hangi kütüphaneyi kullanacağınıza karar vermenize yardımcı olacaktır :)
alt işlem
Alt işlem, harici komutları çağırmanıza ve bunları giriş/çıkış/hata borularına (stdin, stdout ve stderr) bağlamanıza izin verir. Alt işlem çalışan komutlar için varsayılan seçimdir, ancak bazen diğer modüller daha iyidir.
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
işletim sistemi
os "işletim sistemine bağlı işlevsellik" için kullanılır. Ayrıca os.system
ve os.popen
ile harici komutları çağırmak için de kullanılabilir (Not: Ayrıca bir subprocess.popen vardır). os her zaman Shell'i çalıştırır ve ihtiyacı olmayan veya subprocess.run
'un nasıl kullanılacağını bilmeyen insanlar için basit bir alternatiftir.
os.system("ls -l") # run command
os.popen("ls -l").read() # This will run the command and return any output
sh
sh, programları sanki işlevmiş gibi çağırmanıza izin veren bir alt işlem arabirimidir. Bir komutu birden çok kez çalıştırmak istiyorsanız bu kullanışlıdır.
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
plumbum
plumbum, "script benzeri" Python programları için bir kütüphanedir. Fonksiyonlar gibi programları sh
'daki gibi çağırabilirsiniz. Plumbum, Shell olmadan bir boru hattı çalıştırmak istiyorsanız kullanışlıdır.
ls_cmd = plumbum.local("ls -l") # get command
ls_cmd() # run command
pexpect
pexpect, alt uygulamaları üretmenize, kontrol etmenize ve çıktılarında kalıpları bulmanıza olanak sağlar. Bu, Unix'te bir tty bekleyen bir komut için alt işlemlere daha iyi bir alternatiftir.
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')
kumaş
kumaş Python 2.5 ve 2.7 kütüphanesidir. Yerel ve uzak Shell komutlarını çalıştırmanıza izin verir. Fabric, güvenli bir Shell'de (SSH) komutları çalıştırmak için basit bir alternatiftir
fabric.operations.local('ls -l') # Run command as normal
fabric.operations.local('ls -l', capture = True) # Run command and receive output
elçi
elçi "insanlar için alt süreç" olarak bilinir. subprocess
modülünün etrafına kolaylık sarıcı olarak kullanılır.
r = envoy.run("ls -l") # Run command
r.std_out # get output
komutları
commands
os.popen
için sarmalayıcı işlevlerini içerir, ancak subprocess
daha iyi bir alternatif olduğundan Python 3'ten kaldırılmıştır.
Düzenleme, J.F. Sebastian'ın yorumuna dayanıyordu.
Bu gibi şeyler için her zaman fabric
kullanın:
from fabric.operations import local
result = local('ls', capture=True)
print "Content:/n%s" % (result, )
Fakat bu iyi bir araç gibi görünüyor: sh
(Python alt işlem arayüzü) .
Bir örneğe bakın:
from sh import vgdisplay
print vgdisplay()
print vgdisplay('-v')
print vgdisplay(v=True)
"Pexpect" Python kütüphanesini de kontrol edin.
Harici programların/komutların, hatta ssh, ftp, telnet'in, vb. Etkileşimli olarak kontrol edilmesini sağlar.
child = pexpect.spawn('ftp 192.168.0.24')
child.expect('(?i)name .*: ')
child.sendline('anonymous')
child.expect('(?i)password')
Kullanım alt işlem modülü (Python 3):
import subprocess
subprocess.run(['ls', '-l'])
Önerilen standart yoldur. Bununla birlikte, daha karmaşık görevler (borular, çıktılar, girdiler vb.) Oluşturmak ve yazmak için can sıkıcı olabilir.
Python sürümüyle ilgili not: Hala kullanıyorsanız Python 2, subprocess.call benzer şekilde çalışır.
ProTip: shlex.split , run
, call
ve diğer subprocess
işlevlerinin komutlarını ayrıştırmanıza yardımcı olabilir istemediğiniz durumda (ya da yapamazsanız!) onları liste şeklinde sağlar:
import shlex
import subprocess
subprocess.run(shlex.split('ls -l'))
Dış bağımlılıkları önemsemiyorsanız, plumbum :
from plumbum.cmd import ifconfig
print(ifconfig['wlan0']())
En iyi subprocess
sarıcıdır. Çapraz platform, yani hem Windows hem de Unix benzeri sistemlerde çalışıyor. pip install plumbum
tarafından yükleyin.
Başka bir popüler kütüphane sh :
from sh import ifconfig
print(ifconfig('wlan0'))
Ancak, sh
Windows desteğini düşürdü, bu yüzden eskisi kadar harika değil. pip install sh
tarafından yükleyin.
Eğer çağırdığınız komutun çıktısına ihtiyacınız varsa, , Subprocess.check_output (Python 2.7+) kullanabilirsiniz.
>>> subprocess.check_output(["ls", "-l", "/dev/null"])
'crw-rw-rw- 1 root root 1, 3 Oct 18 2007 /dev/null\n'
Ayrıca Shell parametresini not edin.
Eğer Shell
True
ise, belirtilen komut Shell aracılığıyla yürütülecektir. Python'u, çoğu sistem kabuğunda sunduğu gelişmiş kontrol akışı için kullanıyorsanız ve yine de Shell boruları, dosya adı joker karakterleri, ortam değişkeni genişletme ve bir kullanıcının evine genişletme gibi diğer Shell özelliklerine kolay erişim sağlamak istiyorsanız, bu yararlı olabilir dizin. Ancak, Python'un kendisinin birçok Shell benzeri özelliğin uygulamalarını sunduğunu unutmayın (özellikleglob
,fnmatch
,os.walk()
,os.path.expandvars()
,os.path.expanduser()
veshutil
).
Ben buyruklarımı böyle çalıştırıyorum. Bu kod hemen hemen ihtiyacınız olan her şeye sahiptir
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()
Kodunuz önceki Python sürümleriyle uyumluluğu korumak zorunda değilse, subprocess.run
önerilen yaklaşımdır Python 3.5'ten itibaren . Daha tutarlı ve Elçi ile benzer kullanım kolaylığı sunuyor. (Borular gerçi basit değildir. Bkz. Bu soru için nasıl .)
İşte docs 'dan bazı örnekler.
Bir işlem yürütün:
>>> subprocess.run(["ls", "-l"]) # doesn't capture output
CompletedProcess(args=['ls', '-l'], returncode=0)
Başarısız olan koşuda yükseltme:
>>> subprocess.run("exit 1", Shell=True, check=True)
Traceback (most recent call last):
...
subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1
Yakalama çıkışı:
>>> 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')
Denemeyi tavsiye ederim Elçi . Alt işlem için bir sarmalayıcıdır, bu da eski modülleri ve fonksiyonları değiştirmeyi amaçlar . Elçi insanlar için alt süreçtir.
Readme öğesinden örnek kullanım:
>>> 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
''
Boru parçaları da etrafta:
>>> r = envoy.run('uptime | pbcopy')
>>> r.command
'pbcopy'
>>> r.status_code
0
>>> r.history
[<Response 'uptime'>]
Sonuç çıktısı olmadan:
import os
os.system("your command here")
Sonuç çıktısı ile:
import commands
commands.getoutput("your command here")
or
commands.getstatusoutput("your command here")
https://docs.python.org/2/library/subprocess.html
... ya da çok basit bir komut için:
import os
os.system('cat testfile')
Ayrıca Plumbum
>>> 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
os.system
Tamam, ama biraz tarihli. Aynı zamanda çok güvenli değil. Bunun yerine, subprocess
öğesini deneyin. subprocess
, sh komutunu doğrudan çağırmaz ve bu nedenle os.system
öğesinden daha güvenlidir.
Daha fazla bilgi edinin here .
Python'da harici bir komut çağırmak
Basit, CompletedProcess
nesnesini döndüren subprocess.run
öğesini kullanın:
>>> 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)
Python 3.5'ten itibaren, belgeler subprocess.run öğesini önerir:
Alt işlemlerin başlatılması için önerilen yaklaşım, kullanabileceği tüm kullanım durumlarında run () işlevini kullanmaktır. Daha gelişmiş kullanım durumları için, temel Popen arayüzü doğrudan kullanılabilir.
İşte mümkün olan en basit kullanımın bir örneği - ve aynen istendiği gibi:
>>> 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
komutun başarıyla tamamlanmasını bekler, ardından bir CompletedProcess
nesnesini döndürür. Bunun yerine TimeoutExpired
(eğer bir timeout=
argümanı verirseniz) veya CalledProcessError
(eğer başarısız olursa ve check=True
iletirseniz) yükseltebilir.
Yukarıdaki örnekten anlaşılabileceği gibi, stdout ve stderr, varsayılan olarak kendi stdout'unuza ve stderr'inize aktarılır.
Döndürülen nesneyi inceleyebilir ve verilen komutu ve dönüş kodunu görebiliriz:
>>> completed_process.args
'python --version'
>>> completed_process.returncode
0
Çıktıyı yakalamak istiyorsanız, subprocess.PIPE
öğesini uygun stderr
veya stdout
öğelerine iletebilirsiniz:
>>> 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''
(Sürüm bilgisinin stdout yerine stderr'e konması ilginç ve biraz sezgisel buluyorum.)
Bir programlı olarak oluşturulmuş bir dize sağlamaya kolayca bir komut dizesi sağlamaktan (soru sorduğu gibi) kolaylıkla geçebilir. Dizeleri programlı olarak oluşturma. Bu potansiyel bir güvenlik sorunudur. Girdiye güvenmediğinizi varsaymak daha iyidir.
>>> 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'
Unutmayın, yalnızca args
konumsal olarak geçilmelidir.
İşte kaynaktaki asıl imza ve help(run)
:
def run(*popenargs, input=None, timeout=None, check=False, **kwargs):
popenargs
ve kwargs
, Popen
yapıcısına verilir. input
, alt işlemin stdinine yönlendirilecek olan bir bayt dizisi (veya kodlama veya universal_newlines=True
belirtilirse unicode) olabilir.
Belgeler, timeout=
ve check=True
öğelerini benden daha iyi açıklıyor:
Zaman aşımı argümanı Popen.communicate () öğesine iletilir. Zaman aşımı süresi dolduğunda, çocuk işlemi öldürülecek ve beklenecek. TimeoutExpired istisnası, çocuk işlemesi .__ 'na sahip olduktan sonra yeniden oluşturulacak. sona erdirildi.
Eğer kontrol doğruysa ve süreç sıfır olmayan bir çıkış koduyla çıkarsa, a Denilen ProcessError istisnası oluşturulacak. Bunun nitelikleri. istisna bağımsız değişkenleri, çıkış kodunu ve stdout ve stderr if yakalandılar.
ve check=True
için bu örnek bulabildiğimden daha iyi:
>>> subprocess.run("exit 1", Shell=True, check=True) Traceback (most recent call last): ... subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1
İşte belgelerde belirtildiği gibi genişletilmiş bir imza:
subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None, Shell=False, cwd=None, timeout=None, check=False, encoding=None, errors=None)
Bunun sadece ark listesinin konumsal olarak iletilmesi gerektiğini gösterdiğini unutmayın. Kalan argümanları anahtar sözcük argümanları olarak iletin.
Bunun yerine Popen
kullanıldığında? Sadece argümanlara dayanarak kullanım örneği bulmakta zorlanırdım. Popen
öğesinin doğrudan kullanımı, poll
, 'send_signal', 'terminate' ve 'wait' gibi yöntemlerine erişmenizi sağlar.
İşte kaynak içinde verilen Popen
imzası. Bunun bilginin en doğru kapsüllenmesi olduğunu düşünüyorum (help(Popen)
yerine):
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):
Ancak daha fazla bilgi verici olan Popen
belgelerine :
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)
Yeni bir süreçte bir çocuk programı yürütün. POSIX'de, sınıf .__ kullanır. os.execvp () - alt programı yürütme davranışına benzer. Windows'da, sınıf, Windows CreateProcess () işlevini kullanır. Argümanlar Popen aşağıdaki gibidir.
Kalan belgelerin Popen
üzerinde anlaşılması okuyucu için bir alıştırma olarak bırakılacaktır.
Bu kadar basit olabilir:
import os
cmd = "your command"
os.system(cmd)
Kullanın:
import os
cmd = 'ls -al'
os.system(cmd)
os - Bu modül işletim sistemine bağlı işlevselliği kullanmanın taşınabilir bir yolunu sunar.
Daha fazla os
işlevi için, here , belgelerdir.
Dönüş değerlerini test etmek istemiyorsanız subprocess.check_call
kullanışlıdır. Herhangi bir hataya istisna atar.
subprocess ile birlikte shlex kullanmaya meyilliyim (alıntı dizelerin kaçmasını ele almak için):
>>> 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)
os.system
sonuçları saklamanıza izin vermez, bu nedenle sonuçları bir listede saklamak istiyorsanız ya da subprocess.call
işlevi çalışır.
Burada daha önce belirtilmeyen başka bir fark var.
subprocess.Popen
, <command> öğesini bir alt işlem olarak yürütür. Benim durumumda, <b> başka bir programla iletişim kurması gereken <a> dosyasını çalıştırmam gerekiyor, <b>.
Alt işlemi denedim ve yürütme başarılı oldu. Ancak <b> <a> ..__ ile iletişim kuramadı. Her ikisini de terminalden çalıştırdığımda her şey normal.
Bir tane daha: (NOT: kwrite diğer uygulamalardan farklı davranır. Aşağıdakini Firefox ile denerseniz, sonuçlar aynı olmaz.)
os.system("kwrite")
işlevini denerseniz, kullanıcı kwrite kapanana kadar program akışı donar. Bunun üstesinden gelmek için os.system(konsole -e kwrite)
yerine denedim. Bu sefer program akmaya devam etti, ancak kwrite konsolun alt işlemi oldu.
Herkes kwrite'ı alt işlem yapmadan çalıştırır (yani sistem monitöründe ağacın en sol kenarında görünmelidir).
Ben sadeliği için Shell_command oldukça seviyorum. Alt işlem modülünün üstüne inşa edilmiştir.
İşte dokümanlardan bir örnek:
>>> 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
os modülünü kullan
import os
os.system("your command")
Örneğin
import os
os.system("ifconfig")
Utanmaz fiş, bunun için bir kütüphane yazdım: P https://github.com/houqp/Shell.py
Temelde şu an için popen ve shlex için bir sarıcı. Ayrıca, boru komutlarını da destekler, böylece Python'da komutları daha kolay zincirleyebilirsiniz. Böylece şöyle şeyler yapabilirsiniz:
ex('echo hello Shell.py') | "awk '{print $2}'"
Linux altında, bağımsız olarak çalışacak harici bir komut çağırmak istemeniz durumunda (python betiği sona erdikten sonra çalışmaya devam eder), görev biriktiricisi veya / komutu olarak basit bir sıra kullanabilirsiniz
Görev biriktiricisine bir örnek:
import os
os.system('ts <your-command>')
Görev biriktiricisi (ts
) ile ilgili notlar:
Çalıştırılacak eşzamanlı işlem sayısını ("yuvalar") şu şekilde ayarlayabilirsiniz:
ts -S <number-of-slots>
ts
dosyasını yüklemek yönetici ayrıcalıkları gerektirmez. Basit bir make
ile onu kaynaktan indirebilir ve derleyebilirsiniz, yolunuza ekleyin ve bitirdiniz.
Popen'i kullanabilir ve sonra prosedürün durumunu kontrol edebilirsiniz:
from subprocess import Popen
proc = Popen(['ls', '-l'])
if proc.poll() is None:
proc.kill()
Çıkış subprocess.Popen .
Windows'ta subprocess
modülünü içe aktarabilir ve subprocess.Popen()
, subprocess.Popen().communicate()
ve subprocess.Popen().wait()
işlevlerini aşağıdaki gibi çağırarak harici komutları çalıştırabilirsiniz:
# 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)
Çıktı:
This process detail:
python.exe 604 RDP-Tcp#0 4 5,660 K
Herhangi bir komutu çalıştırmanın ve sonucu geri almanın en kolay yolu:
from commands import getstatusoutput
try:
return getstatusoutput("ls -ltr")
except Exception, e:
return None
Ağ kimliğini açık depo nötronundan almak için:
#!/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)
nova ağ listesinin çıktısı
+--------------------------------------+------------+------+
| 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 |
+--------------------------------------+------------+------+
print (networkId) çıktısı
27a74fcd-37c0-4789-9414-9531b7e3f126
İşte iki kuruşum: Benim görüşüme göre, dış komutlarla uğraşırken en iyi yöntem bu.
Bunlar execute metodunun dönüş değerleridir ...
pass, stdout, stderr = execute(["ls","-la"],"/home/user/desktop")
Bu execute metodudur ...
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]
Invoke bir Python (2.7 ve 3.4+) görev yürütme aracı ve kütüphanesidir. Shell komutlarını çalıştırmak için temiz, üst düzey bir API sağlar
>>> 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
İşte harici bir komut çağırıyor ve komutun çıktısını döndürür veya yazdırır:
Python Alt süreç check_output için iyi
Argümanlarla komutu çalıştırın ve çıktısını bir bayt dizesi olarak döndürün.
import subprocess
proc = subprocess.check_output('ipconfig /all')
print proc
Kullanın:
import subprocess
p = subprocess.Popen("df -h", Shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0]
print p.split("\n")
Çalışması daha kolay olan Nice çıktılarını verir:
['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',
'']
Tartışmaya eklemek için, bir Python konsolu kullanmayı eklerseniz, harici komutları IPython 'dan arayabilirsiniz. IPython İsteminde, Shell komutlarını '!' Önekini çağırarak arayabilirsiniz. Python kodunu Shell ile birleştirebilir ve Shell komut dosyalarının çıktısını Python değişkenlerine atayabilirsiniz.
Örneğin:
In [9]: mylist = !ls
In [10]: mylist
Out[10]:
['file1',
'file2',
'file3',]
Python'da harici bir komut çağırmak
Harici bir komut çağırmanın basit bir yolu os.system(...)
işlevini kullanmaktır. Ve bu fonksiyon komutun çıkış değerini döndürür. Ama dezavantajı stdout ve stderr'ı alamayacağımızdır.
ret = os.system('some_cmd.sh')
if ret != 0 :
print 'some_cmd.sh execution returned failure'
Arka planda Python'da harici bir komut çağırmak
subprocess.Popen
, os.system
kullanmak yerine harici bir komut çalıştırmak için daha fazla esneklik sağlar. Arka planda bir komut başlatabilir ve bitmesini bekleyebiliriz. Ondan sonra stdout ve stderr'i alabiliriz.
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
Arka planda Python'da uzun süredir çalışan harici bir komut çağırmak ve bir süre sonra durmak
Arka planda uzun zamandır devam eden bir süreci subprocess.Popen
kullanarak da başlatabilir ve görevi bittiğinde bir süre sonra öldürebiliriz.
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]
Python, .__ 'da harici komutları çalıştırmanın pek çok farklı yolu vardır ve hepsinin kendi artı yönleri ve dezavantajları vardır.
Meslektaşlarım ve ben Python sistem yönetim araçlarını yazıyoruz, bu yüzden birçok harici komut çalıştırmamız gerekiyor ve bazen onların zaman uyumsuz, zaman aşımı, her saniye güncelleme vb.
Dönüş kodunu ve hatalarını ele almanın farklı yolları da vardır, Ve çıktıyı ayrıştırmak ve yeni girdi sağlamak isteyebilirsiniz (bir expect türünde). Veya farklı bir tty (örneğin, ekran kullanırken) çalıştırmak için stdin, stdout ve stderr'i yönlendirmeniz gerekir.
Bu yüzden muhtemelen harici komutun etrafına bir sürü sarmalayıcı yazmanız gerekecek. İşte burada yazdığımız bir Python modülü var. İstediğiniz hemen hemen her şeyi halledebilirsiniz. Eğer istemezseniz, çok esnektir, böylece kolayca genişletebilirsiniz:
https://github.com/hpcugent/vsc-base/blob/master/lib/vsc/utils/run.py
Örnek olarak (Linux'ta):
import subprocess
subprocess.run('mkdir test.dir', Shell=True)
Bu, şu anki dizinde test.dir'yi oluşturur .. __ Bunun da işe yaradığını unutmayın:
import subprocess
subprocess.call('mkdir test.dir', Shell=True)
Os.system kullanarak eşdeğer kod:
import os
os.system('mkdir test.dir')
En iyi uygulama, os yerine alt işlemi kullanmaktır. Alt işlemler hakkında bilmeniz gereken her şey here .Ayrıca, tüm Python belgelerinin here . PDF dosyasını .Zip olarak paketledim. Bunu söylüyorum, çünkü tutorial.pdf'deki os modülüne güzel bir genel bakış (sayfa 81). Ayrıca, Python kodlayıcıları için yetkili bir kaynaktır.
Python 3.5+ için run işlevini alt işlem modülünden kullanmanız önerilir. Bu, çıktıyı ve dönüş kodunu kolayca elde edebileceğiniz bir CompletedProcess
nesnesini döndürür.
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)
Genellikle, aşağıdaki komutları harici komutlar için kullanıyorum ve bu özellikle uzun süren işlemler için kullanışlıdır. Aşağıdaki yöntem işlem çıktısını tails çalışırken ve çıktısını döndürür, işlem başarısız olursa bir istisna oluşturur.
İşlem, poll () işleminde işlem kullanılarak yapılırsa ortaya çıkar.
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)
Bunu şu şekilde çağırabilirsiniz:
exec_long_running_proc(command = "Hive", args=["-f", hql_path])
Os modülünü kullanmak için basit bir yoldur:
import os
os.system('ls')
Alternatif olarak, alt işlem modülünü de kullanabilirsiniz
import subprocess
subprocess.check_call('ls')
Sonucun bir değişkende saklanmasını istiyorsanız:
import subprocess
r = subprocess.check_output('ls')
Kullanım 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(" "))
Popen
__ subprocess
işlevinin kullanılması Python modülü, Linux komutlarını çalıştırmanın en basit yoludur. Bu, Popen.communicate()
işlevi komutlarınızın çıktısını verecektir. Örneğin
import subprocess
..
process = subprocess.Popen(..) # Pass command and arguments to the function
stdout, stderr = process.communicate() # Get command output and error
..
Komut çağırmanın birçok yolu vardır.
and.exe
iki parametreye ihtiyaç duyuyorsa. Cmd içinde şunu söyleyebiliriz sample.exe
şunu kullanın: and.exe 2 3
ve ekranda 5
değerini gösterir.
and.exe
öğesini çağırmak için bir Python betiği kullanırsak, şunu yapmalıyız ..
os.system(cmd,...)
os.system(("and.exe" + " " + "2" + " " + "3"))
os.popen(cmd,...)
os.popen(("and.exe" + " " + "2" + " " + "3"))
subprocess.Popen(cmd,...)
subprocess.Popen(("and.exe" + " " + "2" + " " + "3"))
Çok zor, bu yüzden cmd'ye boşluk bırakabiliriz:
import os
cmd = " ".join(exename,parameters)
os.popen(cmd)
Bir Python not defterinden bir Shell komutu çağırmanız gerekirse ( Jupyter , Zeppelin, Databricks veya Google Cloud Datalab gibi) sadece !
önekini kullanabilirsiniz.
Örneğin,
!ls -ilF
Bu kullanımda yardımcı olacak küçük bir kütüphane yazdım:
https://pypi.org/project/citizenshell/
Kullanarak yüklenebilir
pip install citizenshell
Ve sonra aşağıdaki gibi kullanılır:
from citizenshell import sh
assert sh("echo Hello World") == "Hello World"
Stdout'u stderr'den ayırabilir ve çıkış kodunu aşağıdaki gibi çıkarabilirsiniz:
result = sh(">&2 echo error && echo output && exit 13")
assert result.stdout() == ["output"]
assert result.stderr() == ["error"]
assert result.exit_code() == 13
İşin güzel yanı, çıktıyı işlemeye başlamadan önce temel Shell'in çıkmasını beklemeniz gerekmez:
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 + "!"
wait = false sayesinde satırları mümkün olduğu gibi yazdıracak
>>> It is 14:24:52!
>>> It is 14:24:53!
>>> It is 14:24:54!
>>> It is 14:24:55!
Daha fazla örnek bulunabilir: https://github.com/meuter/citizenshell
Python kullanarak Shell komutlarını çalıştırmanın iki önemli yolu vardır. Aşağıda belirtilen her iki örnek de Python'u kullanarak mevcut çalışma dizininin (pwd
) isminin nasıl alınabileceğini göstermektedir. pwd
yerine herhangi bir Unix komutunu kullanabilirsiniz.
1.> 1. yöntem: Python'da Shell komutlarını çalıştırmak için oradaki os modülünü ve oradaki system () işlevini kullanabilirsiniz.
import os
os.system('pwd')
Çıktı:
/Users/siddharth
1.> 2nd method: Başka bir yol, subprocess modülünü ve call () işlevini kullanmaktır.
import subprocess
subprocess.call('pwd')
Çıktı:
/Users/siddharth
Aşağıdaki "run" yöntemini öneririm ve STDOUT, STDERR ve çıkış statüsünü sözlük olarak almamıza yardımcı olacaktır; Bunun arayanı, sürecin asıl durumunu bilmek için 'run' yöntemiyle sözlük dönüşünü okuyabilir.
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
Bazı araştırmalardan sonra, benim için çok işe yarayan aşağıdaki kod var. Temel olarak stdout ve stderr'yi gerçek zamanlı olarak yazdırır. Umarım ihtiyacı olan birine yardım eder.
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
Sultan bu amaç için hazırlanan son bir ish paketidir. Kullanıcı ayrıcalıklarını yönetme ve yardımcı hata mesajları ekleme konusunda bazı öneriler sunar.
from sultan.api import Sultan
with Sultan.load(Sudo=True, hostname="myserver.com") as sultan:
sultan.yum("install -y tree").run()
Hataları işlemek ve çıktı ve diğer şeyleri yönlendirmek için bir sarmalayıcı yazdım.
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)
Buna şöyle diyebilirsin:
cmd = 'ln -ls "/var/log"'
stdout = 'out.txt'
call_cmd(cmd, stdout)
alt süreç modülü yukarıda Eli tarafından açıklanan çok güçlü, ancak bataklık standart bir sistem çağrısı yapmak ve çıktısını denetlemek için sözdizimi gereksiz yere prolix.
Sistem çağrısı yapmanın en kolay yolu commands modülü ile (yalnızca Linux).
> import commands
> commands.getstatusoutput("grep matter alice-in-wonderland.txt")
(0, "'Then it doesn't matter which way you go,' said the Cat.")
Tuple'daki ilk öğe, sürecin dönüş kodudur. İkinci öğe standart çıktı (ve birleştirilmiş standart hata).
Python aygıtları komut modülünü 'kullanımdan kaldırmıştır', ancak bu kullanmamanız gerektiği anlamına gelmiyor. Sadece artık geliştirmiyorlardı ki, tamam, çünkü zaten mükemmel (küçük ama önemli işlevinde).
Cevapların bazıları python'un önceki sürümleriyle ilişkiliydi ya da os.system
modülünü kullanıyorlardı. Ben bu cevabı python 3.5+
'da subprocess
kullanmak isteyenler için gönderiyorum. Aşağıdaki Linux benim için hile yaptı:
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'))
Dökümantasyon 'de belirtildiği gibi, PIPE
değerleri bayt dizileridir ve bunları doğru şekilde göstermek için kod çözme işlemi dikkate alınmalıdır. Daha sonra python sürümleri için, subprocess.run()
'nin kwarglarına text=True
ve encoding='utf-8'
eklenir.
Yukarıda belirtilen kodun çıktısı:
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
Ayrıca, kullanımdan kaldırılan commands
modülünden Eski Kabuk Arama İşlevleri olan subprocess.getoutput()
ve subprocess.getstatusutput()
işlevlerini kullanabilirsiniz.
subprocess.getstatusoutput(cmd)
Bir Shell'de
exitcode
çalıştırmanın dönüşü (output
name__,cmd
name__).
subprocess.getoutput(cmd)
Shell'de
stdout
çalıştırmanın çıktısını (stderr
vecmd
name__) döndür.
import
ve sonra dosya adını kullanabilirsiniz. Örneğin, dahili 'random' modülünü kullanarak: import random
EğerDEĞILkomutları içinde kullanıcı girişi kullanıyorsanız bunu kullanabilirsiniz.
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()
Ve onu kullan
branch = sh('git rev-parse --abbrev-ref HEAD')
Shell=True
bir Shell doğurur, böylece boru ve bu tür Shell şeylerini sh('ps aux | grep python')
kullanabilirsiniz. Bu, kodlanmış komutları çalıştırmak ve çıktısını işlemek için çok kullanışlıdır. universal_lines=True
çıktının ikili yerine bir dizgede döndüğünden emin olun.
cwd=getcwd()
, komutun yorumlayıcı ile aynı çalışma diziniyle çalıştırıldığından emin olur. Bu, git komutlarının yukarıdaki git şube adı örneği gibi çalışması için kullanışlıdır.
Bazı tarifler
sh('free -m').split('\n')[1].split()[1]
sh('df -m /').split('\n')[1].split()[4][0:-1]
sum(map(float, sh('ps -ef -o pcpu').split('\n')[1:])
Ancak bu, dokümanlardan kullanıcı girişi için güvenli değildir:
Güvenlik Hususları¶
Diğer bazı açılır fonksiyonların aksine, bu uygulama hiçbir zaman örtük olarak bir sistem Kabuğu çağırmaz. Bu, Shell meta karakterleri dahil tüm karakterlerin güvenli bir şekilde alt işlemlere geçirilebileceği anlamına gelir. Eğer Shell açıkça çağrılırsa, Shell = True aracılığıyla, Shell boşluklarını önlemek için tüm boşlukların ve meta karakterlerin uygun şekilde alıntılanmasını sağlamak, uygulamanın sorumluluğundadır.
Shell = True kullanıldığında, shlex.quote () işlevi, Shell komutlarını oluşturmak için kullanılacak dizelerdeki boşluklardan ve Shell meta karakterlerinden düzgün şekilde kaçmak için kullanılabilir.
shlex.quote()
işlevini kullanmak bile, Shell komutlarında kullanıcı girişlerini kullanırken biraz paranoyaklık tutmak iyidir. Bir seçenek, bazı genel çıktılar almak ve kullanıcı girdisine göre filtrelemek için bir sabit kod komutu kullanmaktır. Her neyse, Shell=False
kullanarak sadece yürütmek istediğiniz tam olarak işlemin yürütüleceğinden ya da bir No such file or directory
hatası alacağınızdan emin olun.
Ayrıca Shell=True
üzerinde bir performans etkisi var, testlerimden Shell=False
'dan (varsayılan) yaklaşık% 20 daha yavaş görünüyor.
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
Bir Python Shell betiği yazıyorsanız ve sisteminizde IPython kurulu ise, IPython içinde bir komut çalıştırmak için bang sihirini kullanabilirsiniz:
!ls
filelist = !ls