Harici bir komutu Python betiğinden (Unix kabuğuna veya Windows komut istemine yazmışım gibi) nasıl çağırırsınız?
Harici bir komutu Python betiğinden (Unix kabuğuna veya Windows komut istemine yazmışım gibi) nasıl çağırırsınız?
Yanıtlar:
Standart kitaplıktaki alt işlem modülüne bakın :
import subprocess
subprocess.run(["ls", "-l"])
Avantajı subprocess
vs. system
onu (alabilirsiniz daha esnek olmasıdır stdout
, stderr
"gerçek" durum kodu, daha iyi hata işleme, vs ...).
Resmi belgeler önerir subprocess
alternatif üzerinde modülü os.system()
:
subprocess
Modül yeni süreçler yumurtlama ve onların sonuçlarını almak için, daha güçlü olanaklar sağlar; bu modülü kullanmak bu işlevi kullanmaktan daha çok tercih edilir [os.system()
].
Belgedeki Eski İşlevleri Alt İşlem Modülü ile Değiştirme bölümü subprocess
bazı yararlı tariflere sahip olabilir.
3.5'ten önceki Python sürümleri için şunu kullanın call
:
import subprocess
subprocess.call(["ls", "-l"])
shell=True
çalışması için kullanmanız gerekecek .
shell=True
, bu amaçla Python os.path.expandvars ile birlikte gelir . Durumda da yazabilirsiniz: os.path.expandvars("$PATH")
. @SethMMorton lütfen yorumunuzu tekrar gözden geçirin -> Neden shell kullanmıyorsunuz = True
for
döngüde birden çok komut çalıştırmak istiyorsanız python betiğimi engellemeden nasıl yapabilirim? Ben sadece bir sürü çalıştırmak istiyorum komutun çıktı umurumda değil.
subprocess
ne zaman kullanılabileceği bir listeden bir liste oluşturmak istiyorsanız , bunu yapmanın kolay bir yolu için shell=False
kullanın docs.python.org/2/library/shlex.html#shlex.splitshlex.split
Dış programları çağırmanın yollarının ve her birinin avantaj ve dezavantajlarının bir özeti:
os.system("some_command with args")
komutu ve bağımsız değişkenleri sisteminizin kabuğuna iletir. Bu çok hoş çünkü aslında bu şekilde birden fazla komutu aynı anda çalıştırabilir ve kanallar ile giriş / çıkış yeniden yönlendirmesini ayarlayabilirsiniz. Örneğin:
os.system("some_command < input_file | another_command > output_file")
Bununla birlikte, bu uygun olsa da, boşluklar, vb. Gibi kabuk karakterlerinden kaçmayı elle işlemeniz gerekir. Diğer yandan, bu aynı zamanda aslında harici programlar değil, sadece kabuk komutları olan komutları çalıştırmanıza izin verir. Belgelere bakın .
stream = os.popen("some_command with args")
os.system
bu işlem için standart girdi / çıktıya erişmek için kullanabileceğiniz dosya benzeri bir nesne vermesi dışında aynı işlemi yapar. Tümünün i / o'yu biraz farklı şekilde ele alan 3 farklı popen varyantı vardır. Her şeyi bir dize olarak iletirseniz, komutunuz kabuğa aktarılır; onları bir liste olarak iletirseniz, hiçbir şeyden kaçma konusunda endişelenmenize gerek yoktur. Belgelere bakın .
Popen
Sınıf subprocess
modülü. Bunun yerine geçmesi amaçlanmıştır, os.popen
ancak bu kadar 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()
onun yerine:
print os.popen("echo Hello World").read()
ancak tüm seçeneklerin 4 farklı popen işlevi yerine tek bir sınıfta olması güzel. Belgelere bakın .
call
İşlev subprocess
modülü. Bu temelde Popen
sınıf gibidir ve aynı argümanların tümünü alır, ancak komut tamamlanana ve size dönüş kodunu verene kadar bekler. Örneğin:
return_code = subprocess.call("echo Hello World", shell=True)
Belgelere bakın .
Python 3.5 veya subprocess.run
üstündeyseniz, yukarıdakine çok benzer, ancak daha esnek olan ve CompletedProcess
komutun yürütülmesi tamamlandığında bir nesneyi döndüren yeni işlevi kullanabilirsiniz .
Os modülü ayrıca bir C programında bulunan tüm fork / exec / spawn işlevlerine sahiptir, ancak bunları doğrudan kullanmanızı önermiyorum.
subprocess
Modül muhtemelen Kullandığınız olmalıdır.
Son olarak, kabuk tarafından bir dize olarak yürütülecek son komutu ilettiğiniz tüm yöntemlerde ve bu komuttan kaçmaktan sorumlu olduğunuzu lütfen unutmayın. Geçirdiğiniz dizenin herhangi bir bölümüne tam olarak güvenilemiyorsa , ciddi güvenlik etkileri vardır . Örneğin, kullanıcı dizenin bir kısmını / herhangi bir kısmını giriyorsa. Emin değilseniz, bu yöntemleri yalnızca sabitlerle kullanın. Etkileri hakkında bir ipucu vermek için şu kodu göz önünde bulundurun:
print subprocess.Popen("echo %s " % user_input, stdout=PIPE).stdout.read()
ve kullanıcının "annem beni sevmediğini && rm -rf /" bir şeyler girdiğini ve tüm dosya sistemini silebileceğini hayal edin.
open
.
subprocess.run()
. docs.python.org/3.5/library/subprocess.html#subprocess.run
subprocess.run(..)
tam olarak ne yaptığını , "Bu, varsayılan olarak stdout veya stderr'yi yakalamak gelmez." ima etmek? Peki ya subprocess.check_output(..)
STDERR?
echo
Geçirilen dizenin ön kısmına dikkat edin Popen
? Yani tam komut olacak echo my mama didnt love me && rm -rf /
.
subprocess.run()
ya da onun büyük kardeşlerine ihtiyacı vardır subprocess.check_call()
. Bu yeterli değil durumlar için, bkz subprocess.Popen()
. os.popen()
belki de hiç bahsedilmemeli, hatta "kendi çatalını / exec / spawn kodunu hacklemeden" sonra bile gelmemelidir.
Tipik uygulama:
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()
Borudaki stdout
verilerle istediğinizi yapmakta özgürsünüz . Aslında, bu parametreleri ( stdout=
ve stderr=
) atlayabilirsiniz ve bu şekilde davranacaktır os.system()
.
.readlines()
tüm satırları aynı anda okur , yani alt işlem çıkana kadar bloke olur (borunun ucunu kapatır). Gerçek zamanlı olarak okumak için (arabellekleme sorunu yoksa) şunları yapabilirsiniz:for line in iter(p.stdout.readline, ''): print line,
p.stdout.readline()
(not: bir s
ucunda) alt onun tampon doldurana kadar herhangi bir veri olmaz. Çocuk çok fazla veri üretmezse, çıktı gerçek zamanlı olmayacaktır. Q'daki ikinci nedene bakın : Neden sadece bir boru (popen ()) kullanmıyorsunuz? . Bu cevapta bazı geçici çözümler sunulmaktadır (pexpect, pty, stdbuf)
Popen
basit görevler için tavsiye etmemeliyiz . Bu da gereksiz yere belirtir shell=True
. subprocess.run()
Cevaplardan birini deneyin .
Çocuk sürecini çağıran süreçten ayırmaya ilişkin bazı ipuçları (alt süreçte arka planda başlanması)
Bir CGI betiğinden uzun bir görev başlatmak istediğinizi varsayalım. Yani, alt işlem CGI betiği yürütme işleminden daha uzun yaşamalıdır.
Alt işlem modülü belgelerinden 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 'alt işlem çağrısı' satırında beklemek istememenizdir. Ancak örnekten 'burada biraz daha kod' satırından sonra ne olduğu belli değil.
Hedef platformum FreeBSD'ydi, ancak geliştirme Windows'taydı, bu yüzden önce Windows'ta sorunla karşılaştım.
Windows'ta (Windows XP), longtask.py çalışmasını bitirinceye kadar üst işlem tamamlanmaz. Bir CGI betiğinde istediğiniz şey değildir. Sorun Python'a özgü değildir; PHP topluluğunda problemler aynıdır.
Çözüm DETACHED_PROCESS İşlem Oluşturma Bayrağını Windows API'sındaki temel CreateProcess işlevine iletmektir. Pywin32'yi kurduysanız, bayrağı win32process modülünden içe aktarabilirsiniz, aksi takdirde kendiniz tanımlamanız gerekir:
DETACHED_PROCESS = 0x00000008
pid = subprocess.Popen([sys.executable, "longtask.py"],
creationflags=DETACHED_PROCESS).pid
/ * UPD 2015.10.27 @eryksun, aşağıdaki yorumda, anlamsal olarak doğru bayrağın CREATE_NEW_CONSOLE (0x00000010) * /
FreeBSD'de başka bir sorunumuz daha var: üst süreç bittiğinde, alt süreçleri de bitirir. Ve bu da bir CGI betiğinde istediğiniz şey değil. Bazı deneyler, sorunun sys.stdout paylaşımında olduğunu gösterdi. Ve çalışma çözümü şuydu:
pid = subprocess.Popen([sys.executable, "longtask.py"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
Diğer platformlarda kodu kontrol etmedim ve FreeBSD'de davranışın nedenlerini bilmiyorum. Herkes bilirse, lütfen fikirlerinizi paylaşın. Python'da arka plan işlemlerini başlatmaya gitmek, henüz hiç ışık tutmaz.
DETACHED_PROCESS
içinde creationflags
miras veya bir konsol oluşturmasını çocuğu önleyerek kaçınır bu. Bunun yerine yeni bir konsol istiyorsanız, CREATE_NEW_CONSOLE
(0x00000010) kullanın .
os.devnull
bazı konsol programlarının bir hatayla çıkış yaptığı için standart tanıtıcıları ayarlamanız gerekebilir . Alt işlemin kullanıcıyla üst işlemle aynı anda etkileşime girmesini istediğinizde yeni bir konsol oluşturun. Her ikisini de tek bir pencerede yapmaya çalışmak kafa karıştırıcı olurdu.
import os
os.system("your command")
Komutun temizlenmediği için bunun tehlikeli olduğunu unutmayın. 'Os' ve 'sys' modülleri ile ilgili dokümantasyon için google'a bırakıyorum. Benzer şeyler yapacak bir sürü işlev (exec * ve spawn *) vardır.
subprocess
biraz daha çok yönlü ve taşınabilir bir çözüm olarak gösterilmelidir. Harici komutları çalıştırmak elbette doğası gereği kaydedilemez (komutun desteklemeniz gereken her mimaride mevcut olduğundan emin olmanız gerekir) ve harici bir komut olarak kullanıcı girişini geçmek doğal olarak güvensizdir.
Ben kullanarak tavsiye ediyorum altişlem sizin için kaçan kabuk ve çok daha güvenli nedenle çünkü modülü yerine os.system.
subprocess.call(['ping', 'localhost'])
subprocess
ne zaman kullanılabileceği bir listeden bir liste oluşturmak istiyorsanız , bunu yapmanın kolay bir yolu için shell=False
kullanın docs.python.org/2/library/shlex.html#shlex.split ( docs.python.org/2/library/subprocess.html#popen-constructor ) dokümanına göre önerilen yol budurshlex.split
import os
cmd = 'ls -al'
os.system(cmd)
Komutun sonuçlarını döndürmek istiyorsanız, kullanabilirsiniz os.popen
. Ancak, diğer yanıtların iyi kapsadığı alt işlem modülü lehine sürüm 2.6'dan bu yana kullanımdan kaldırılmıştır .
Python ile harici komutları çağırmanıza izin veren birçok farklı kitaplık var. Her kütüphane için bir açıklama verdim ve harici bir komut çağırma örneği gösterdim. Örnek olarak kullandığım komut ls -l
(tüm dosyaları listele). Kütüphanelerden herhangi biri hakkında daha fazla bilgi edinmek isterseniz, her birinin belgelerini listeledim ve bağladım.
Kaynaklar:
Bunların hepsi kütüphaneler:
Umarım bu hangi kütüphaneyi kullanacağınıza karar vermenize yardımcı olacaktır :)
altişlem
Alt işlem, harici komutları çağırmanıza ve bunları giriş / çıkış / hata kanallarına (stdin, stdout ve stderr) bağlamanıza olanak tanır. Alt işlem komutları çalıştırmak 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. Harici komutları os.system
ve ile çağırmak için de kullanılabilir os.popen
(Not: Ayrıca bir subprocess.popen vardır). os her zaman kabuğu çalıştıracak ve kullanması gerekmeyen veya nasıl kullanılacağını bilmeyen insanlar için basit bir alternatiftir subprocess.run
.
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ızı sağlayan bir alt işlem arabirimidir. Bir komutu birden çok kez çalıştırmak istiyorsanız bu yararlı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. Gibi işlevler gibi programları çağırabilirsiniz sh
. Plumbum, kabuksuz bir boru hattı çalıştırmak istiyorsanız yararlıdır.
ls_cmd = plumbum.local("ls -l") # get command
ls_cmd() # run command
pexpect
pexpect, çocuk uygulamalarını oluşturmanıza, kontrol etmenize ve çıktılarında desen bulmanıza olanak tanır. Bu, Unix'te tty bekleyen komutlar için alt işleme daha iyi bir alternatiftir.
pexpect.run("ls -l") # Run command as normal
child = pexpect.spawn('scp foo user@example.com:.') # Spawns child application
child.expect('Password:') # When this is the output
child.sendline('mypassword')
kumaş
fabric bir Python 2.5 ve 2.7 kütüphanesidir. Yerel ve uzak kabuk komutlarını yürütmenizi sağlar. Yapı, komutları güvenli bir kabukta (SSH) ç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 çevresinde kolaylık sağlayan bir ambalaj olarak kullanılır .
r = envoy.run("ls -l") # Run command
r.std_out # get output
komutlar
commands
için sarmalayıcı işlevler içerir os.popen
, ancak subprocess
daha iyi bir alternatif olduğu için Python 3'ten kaldırılmıştır .
Düzenleme JF Sebastian'ın yorumuna dayanıyordu.
Her zaman fabric
böyle şeyler için kullanıyorum:
from fabric.operations import local
result = local('ls', capture=True)
print "Content:/n%s" % (result, )
Ama 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 vb. Etkileşimli kontrolüne izin verir. Sadece şöyle bir şey yazabilirsiniz:
child = pexpect.spawn('ftp 192.168.0.24')
child.expect('(?i)name .*: ')
child.sendline('anonymous')
child.expect('(?i)password')
Alt işlem modülünü kullanın (Python 3):
import subprocess
subprocess.run(['ls', '-l'])
Önerilen standart yöntemdir. Ancak, daha karmaşık görevler (borular, çıktılar, girdiler, vb.) Oluşturmak ve yazmak sıkıcı olabilir.
Python sürümü hakkında not: Hala Python 2 kullanıyorsanız, subprocess.call benzer şekilde çalışır.
ProTip: shlex.split için komutu ayrıştırmak için yardımcı olabilir run
, call
ve diğer subprocess
durumda fonksiyonları istemediğiniz (ya yapamazsın!) Listeleri şeklinde bunları sağlamak:
import shlex
import subprocess
subprocess.run(shlex.split('ls -l'))
Dış bağımlılıklara aldırmazsanız , plumbum kullanın :
from plumbum.cmd import ifconfig
print(ifconfig['wlan0']())
En iyi subprocess
sarıcıdır. Platformlar arası, yani hem Windows hem de Unix benzeri sistemlerde çalışır. Tarafından yükleyin pip install plumbum
.
Başka bir popüler kütüphane sh :
from sh import ifconfig
print(ifconfig('wlan0'))
Ancak, sh
Windows desteği düştü, bu yüzden eskisi kadar harika değil. Tarafından yükleyin pip install sh
.
Aradığı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 de not edin .
Kabuk ise
True
, belirtilen komut kabuk üzerinden yürütülür. Python'u öncelikle sistem kabuklarının çoğunda sunduğu gelişmiş kontrol akışı için kullanıyorsanız ve yine de kabuk boruları, dosya adı joker karakterleri, ortam değişkeni genişletmesi ve ~ bir kullanıcının evine genişletilmesi gibi diğer kabuk özelliklerine kolayca erişmek istiyorsanız faydalı olabilir. dizin. Ancak, not Python kendisinin uygulamalarını sunduğu birçok kabuk gibi özellikleri (özellikleglob
,fnmatch
,os.walk()
,os.path.expandvars()
,os.path.expanduser()
, veshutil
).
check_output
Dize yerine bir liste gerektiren bir not . Çağrınızı geçerli kılmak için alıntı yapılan alanlara güvenmiyorsanız, bunu yapmanın en basit, en kolay yolu subprocess.check_output("ls -l /dev/null".split())
.
Komutlarımı bu şekilde çalıştırıyorum. Bu kodda ihtiyacınız olan her şey var
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()
subprocess.run
kodunuzun önceki Python sürümleriyle uyumluluğu sürdürmesi gerekmiyorsa , Python 3.5'ten itibaren önerilen yaklaşımdır . Daha tutarlı ve Elçi ile benzer kullanım kolaylığı sunuyor. (Boru basit düşünce olarak değil. Bkz nasıl bu soruyu .)
Belgelerden bazı örnekler .
Bir işlem çalıştırın:
>>> subprocess.run(["ls", "-l"]) # Doesn't capture output
CompletedProcess(args=['ls', '-l'], returncode=0)
Başarısız çalıştırmada 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')
Elçi'yi denemenizi tavsiye ederim . Alt süreç için bir sargıdır, bu da eski modülleri ve işlevleri değiştirmeyi amaçlamaktadır . Elçi insanlar için bir alt süreçtir.
README'den ö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
''
Etrafında boru şeyler:
>>> r = envoy.run('uptime | pbcopy')
>>> r.command
'pbcopy'
>>> r.status_code
0
>>> r.history
[<Response 'uptime'>]
os.system
Tamam, ama tür tarihli. Ayrıca çok güvenli değil. Bunun yerine deneyin subprocess
. subprocess
sh'yi doğrudan çağırmaz ve bu nedenle daha güvenlidir os.system
.
Daha fazla bilgiyi buradan edinebilirsiniz .
subprocess
tüm güvenlik sorunlarını ortadan kaldırmaz ve kendi başına bazı sinir bozucu sorunları vardır.
Python'da harici bir komut çağırma
Basit, kullanım subprocess.run
, bir CompletedProcess
nesne döndürür :
>>> 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 itibariyle, belgeler subprocess.run öğesini önerir :
Alt süreçleri çağırmak için önerilen yaklaşım, işleyebileceği tüm kullanım durumları için run () işlevini kullanmaktır. Daha gelişmiş kullanım durumları için, temeldeki Popen arabirimi doğrudan kullanılabilir.
İşte mümkün olan en basit kullanıma bir örnek - ve tam olarak istendiği gibi yapıyor:
>>> 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 bitmesini bekler, sonra bir CompletedProcess
nesneyi döndürür . Bunun yerine TimeoutExpired
(bir timeout=
argüman verirseniz ) veya CalledProcessError
(başarısız olursa ve geçerseniz check=True
) yükselebilir .
Yukarıdaki örnekten çıkarım yapabileceğiniz gibi, hem stdout hem de stderr varsayılan olarak kendi stdout'unuza ve stderr'ye 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
, uygun olana geçebilir stderr
veya stdout
:
>>> 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'a konmasını ilginç ve biraz mantıksız buluyorum.)
Manuel olarak bir komut dizesi sağlamaktan (sorunun önerdiği gibi) programlı olarak oluşturulmuş bir dize sağlamaya kolayca geçilebilir. Programlı olarak dizeler oluşturmayın. 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'
Not, sadece args
konumsal olarak geçilmelidir.
Kaynakta ve şu şekilde gösterildiği gibi gerçek imza help(run)
:
def run(*popenargs, input=None, timeout=None, check=False, **kwargs):
popenargs
Ve kwargs
verilen Popen
yapıcı. alt işlemin stdinine input
bağlanacak bir bayt dizesi (veya kodlama belirtilirse unicode veya universal_newlines=True
) olabilir.
Belgeler açıklayabilir timeout=
ve check=True
yapabileceğimden daha iyi:
Zaman aşımı argümanı Popen.communicate () öğesine iletilir. Zaman aşımı süresi dolarsa, alt süreç öldürülecek ve beklenecektir. Alt süreç sona erdikten sonra TimeoutExpired özel durumu yeniden yükseltilecektir.
Kontrol doğruysa ve işlem sıfırdan farklı bir çıkış koduyla çıkarsa, CalledProcessError istisnası yükseltilir. Bu kural dışı durumun öznitelikleri, yakalandıysa bağımsız değişkenleri, çıkış kodunu ve stdout ve stderr öğelerini içerir.
ve bu örnek check=True
, gelebileceğimden daha iyidir:
>>> subprocess.run("exit 1", shell=True, check=True) Traceback (most recent call last): ... subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1
Dokümanlarda verildiğ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 yalnızca argüman listesinin konumsal olarak geçirilmesi gerektiğini gösterdiğini unutmayın. Bu nedenle, kalan bağımsız değişkenleri anahtar kelime bağımsız değişkenleri olarak iletin.
Popen
Bunun yerine ne zaman kullanılır ? Sadece argümanlara dayanarak kullanım davası bulmakta zorlanıyordum. Popen
Bununla birlikte, doğrudan kullanımı poll
, 'send_signal', 'terminate' ve 'wait' gibi yöntemlerine erişmenizi sağlar .
Burada Popen
kaynakta verilen imza . Bu (en aksine help(Popen)
) bilginin en kesin kapsüllenmesi olduğunu düşünüyorum :
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):
Ama daha bilgilendirici Popen
belgeler :
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 alt program yürütün. POSIX'te sınıf, alt programı yürütmek için os.execvp () benzeri davranışı kullanır. Windows'ta, sınıf Windows CreateProcess () işlevini kullanır. Popen ile ilgili argümanlar aşağıdaki gibidir.
İle ilgili kalan dokümantasyonu anlama Popen
okuyucu için bir alıştırma olarak bırakılacaktır.
shell=True
komutun liste halinde olması veya (daha iyisi) geçmesi gerekir.
Orada da 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
kullanın:
import os
cmd = 'ls -al'
os.system(cmd)
os - Bu modül işletim sistemine bağlı işlevselliği kullanmak için taşınabilir bir yol sağlar.
Daha fazla os
fonksiyon için, dokümantasyon burada .
Bu kadar basit olabilir:
import os
cmd = "your command"
os.system(cmd)
os.system
açıkça lehine kaçınmayı önerir subprocess
.
Sadeliği için shell_command'ı çok seviyorum . Alt işlem modülünün üzerine inşa edilmiştir.
Belgelerden 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
Burada daha önce bahsedilmeyen başka bir fark var.
subprocess.Popen
<komut> seçeneğini bir alt işlem olarak yürütür. Benim durumumda, başka bir programla iletişim kurması gereken <a> dosyasını yürütmem gerekiyor <b>.
Alt süreci 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ğıdakileri Firefox ile denerseniz, sonuçlar aynı olmayacaktır.)
Eğer denerseniz os.system("kwrite")
, program akış donar kullanıcı kapanır KWRITE kadar. Bunun üstesinden gelmek için denedim os.system(konsole -e kwrite)
. Bu zaman programı akmaya devam etti, ancak kwrite konsolun alt süreci oldu.
Herkes kwrite'ı bir alt işlem olarak çalıştırmaz (yani sistem monitöründe ağacın en sol kenarında görünmelidir).
os.system
sonuçları depolamanıza izin vermez, bu nedenle sonuçları bir listede veya başka bir şeyde saklamak istiyorsanız, bir subprocess.call
çalışma.
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 sargı. Ayrıca boru komutlarını da destekler, böylece Python'da komutları daha kolay zincirleyebilirsiniz. Böylece aşağıdakileri yapabilirsiniz:
ex('echo hello shell.py') | "awk '{print $2}'"
Windows sadece alabilirsiniz subprocess
modülü ve arayarak dış komutları çalıştırın subprocess.Popen()
, subprocess.Popen().communicate()
ve subprocess.Popen().wait()
aşağıdaki gibi:
# 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
Linux altında, bağımsız olarak yürütülecek (python komut dosyası sona erdikten sonra çalışmaya devam edecek) harici bir komut çağırmak isterseniz, basit bir kuyruğu görev biriktiricisi veya at komutu olarak kullanabilirsiniz.
Görev biriktiricili bir örnek:
import os
os.system('ts <your-command>')
Görev biriktirici ( ts
) ile ilgili notlar :
Çalıştırılacak eşzamanlı işlemlerin sayısını ("yuvalar") şu şekilde ayarlayabilirsiniz:
ts -S <number-of-slots>
Yüklemek ts
için yönetici ayrıcalıkları gerekmez. Basit bir şekilde kaynaktan indirip derleyebilir make
, yolunuza ekleyebilirsiniz ve işiniz bitti.
ts
işaretçi at
hafif faydalı olsa da, bildiğim herhangi bir dağıtımda standart değil . Muhtemelen de bahsetmelisiniz batch
. Başka yerlerde olduğu gibi, os.system()
öneri muhtemelen en azından subprocess
önerilen değiştirilmesinden bahsetmelidir .
Popen'i kullanabilir ve ardından prosedürün durumunu kontrol edebilirsiniz:
from subprocess import Popen
proc = Popen(['ls', '-l'])
if proc.poll() is None:
proc.kill()
Alt süreci kontrol edin .
Ağ kimliği getirmesi openstack Neutron :
#!/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 net 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 |
+--------------------------------------+------------+------+
Çıktı baskı (NETWORKID)
27a74fcd-37c0-4789-9414-9531b7e3f126
os.popen()
2016'da önerilmemelisiniz . Awk betiği kolayca yerel Python kodu ile değiştirilebilir.
echo $PATH
kullanarak yapmaya çalıştımcall(["echo", "$PATH"])
, ama$PATH
herhangi bir yerine koymak yerine gerçek dizeyi yankıladı . PATH ortam değişkenini alabileceğimi biliyorum, ama komutun tam olarak bash'de yapmışım gibi davranmanın kolay bir yolu olup olmadığını merak ediyorum.