Bu sorunun cevabı kullandığınız Python sürümüne bağlıdır. En basit yaklaşım subprocess.check_output
işlevi kullanmaktır :
>>> subprocess.check_output(['ls', '-l'])
b'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
check_output
yalnızca bağımsız değişkenleri girdi olarak alan tek bir program çalıştırır. 1 Sonucu tam olarak yazdırıldığı gibi döndürür stdout
. Giriş yazmanız gerekirse stdin
, run
veya Popen
bölümlerine atlayın . Karmaşık kabuk komutlarını yürütmek istiyorsanız shell=True
, bu cevabın sonundaki nota bakın .
Bu check_output
fonksiyon Python'un neredeyse tüm sürümlerinde hala yaygın olarak kullanılmaktadır (2.7+). 2 Ancak daha yeni sürümler için, artık önerilen yaklaşım değildir.
Modern Python sürümleri (3.5 veya üstü): run
Python 3.5 veya üstünü kullanıyorsanız ve geriye dönük uyumluluğa ihtiyacınız yoksa , yeni run
işlev önerilir. subprocess
Modül için çok genel, yüksek düzeyli bir API sağlar . Bir programın çıktısını yakalamak için subprocess.PIPE
bayrağı stdout
anahtar kelime değişkenine iletin. Ardından stdout
, döndürülen CompletedProcess
nesnenin özniteliğine erişin :
>>> import subprocess
>>> result = subprocess.run(['ls', '-l'], stdout=subprocess.PIPE)
>>> result.stdout
b'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
Dönüş değeri bir bytes
nesnedir, bu nedenle uygun bir dize istiyorsanız decode
buna ihtiyacınız olacaktır . Aranan işlemin UTF-8 kodlu bir dize döndürdüğü varsayılarak:
>>> result.stdout.decode('utf-8')
'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
Bunların hepsi bir astarla sıkıştırılabilir:
>>> subprocess.run(['ls', '-l'], stdout=subprocess.PIPE).stdout.decode('utf-8')
'total 0\n-rw-r--r-- 1 memyself staff 0 Mar 14 11:04 files\n'
İşlemin girdisine veri iletmek istiyorsanız , anahtar kelime bağımsız değişkenine stdin
bir bytes
nesne input
iletin:
>>> cmd = ['awk', 'length($0) > 5']
>>> input = 'foo\nfoofoo\n'.encode('utf-8')
>>> result = subprocess.run(cmd, stdout=subprocess.PIPE, input=input)
>>> result.stdout.decode('utf-8')
'foofoo\n'
Hataları stderr=subprocess.PIPE
(yakalama result.stderr
) veya stderr=subprocess.STDOUT
( result.stdout
normal çıktıyla birlikte yakalama ) ileterek yakalayabilirsiniz . Güvenlik endişe verici değilse, shell=True
aşağıdaki notlarda açıklandığı gibi ileterek daha karmaşık kabuk komutları da çalıştırabilirsiniz .
Bu, eski işleri yapmanın biçimine kıyasla biraz karmaşıklık katıyor. Ama bence getiriye değer: şimdi run
sadece işlevle yapmak için ihtiyacınız olan hemen hemen her şeyi yapabilirsiniz .
Eski Python sürümleri (2.7-3.4): check_output
Python'un daha eski bir sürümünü kullanıyorsanız ya da geriye doğru uyumluluğa ihtiyacınız varsa, check_output
işlevi yukarıda kısaca açıklandığı gibi kullanabilirsiniz. Python 2.7'den beri mevcuttur.
subprocess.check_output(*popenargs, **kwargs)
Alır Popen
(aşağıya bakınız) ile aynı argümanları alır ve programın çıktısını içeren bir dize döndürür. Bu cevabın başlangıcında daha ayrıntılı bir kullanım örneği var. Python 3.5 ve daha büyük check_output
sürümlerde run
, check=True
ve ile çalışmak ve stdout=PIPE
yalnızca stdout
öznitelik döndürmekle eşdeğerdir .
Sen geçebilir stderr=subprocess.STDOUT
döndü çıktıda yer aldığını hata iletileri sağlamak için - ama Python geçen bazı sürümlerinde stderr=subprocess.PIPE
için check_output
teneke neden çözümsüzlüklerle . Güvenlik endişe verici değilse, shell=True
aşağıdaki notlarda açıklandığı gibi ileterek daha karmaşık kabuk komutları da çalıştırabilirsiniz .
İşlemden boru hattına geçmeniz stderr
veya işlemden check_output
geçirmeniz gerekiyorsa, görev kadar olmayacaktır. Bkz Popen
bu durumda aşağıdaki örnekleri.
Karmaşık uygulamalar ve Python'un eski sürümleri (2.6 ve altı): Popen
Geriye dönük uyumluluğa ihtiyacınız varsa veya check_output
sağladığınızdan daha karmaşık bir işlevsellik istiyorsanız, doğrudan Popen
alt işlemler için düşük düzeyli API'yi içine alan nesnelerle çalışmanız gerekir .
Popen
Yapıcı kabul eden , tek bir komut bağımsız değişken olmayan ya da bir liste bağımsız değişkenler herhangi bir sayıda, listedeki ayrı bir madde olarak, her takip ettiği ilk madde olarak bir komut ihtiva ederler. shlex.split
dizeleri uygun şekilde biçimlendirilmiş listelerde ayrıştırmaya yardımcı olabilir. Popen
nesneler ayrıca işlem GÇ yönetimi ve düşük düzeyli yapılandırma için bir dizi farklı argümanı da kabul eder .
Girdi ve yakalama çıktısı göndermek için communicate
, neredeyse her zaman tercih edilen yöntemdir. De olduğu gibi:
output = subprocess.Popen(["mycmd", "myarg"],
stdout=subprocess.PIPE).communicate()[0]
Veya
>>> import subprocess
>>> p = subprocess.Popen(['ls', '-a'], stdout=subprocess.PIPE,
... stderr=subprocess.PIPE)
>>> out, err = p.communicate()
>>> print out
.
..
foo
Ayarlarsanız stdin=PIPE
, communicate
verileri işleme yoluyla şu yolla aktarmanıza da olanak tanır stdin
:
>>> cmd = ['awk', 'length($0) > 5']
>>> p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
... stderr=subprocess.PIPE,
... stdin=subprocess.PIPE)
>>> out, err = p.communicate('foo\nfoofoo\n')
>>> print out
foofoo
Not Aaron Hall'un cevabı bazı sistemlerde belirtir, sette gerekebilir stdout
, stderr
ve stdin
tüm PIPE
(veya DEVNULL
) almak için communicate
hiç işe.
Bazı nadir durumlarda, karmaşık, gerçek zamanlı çıktı yakalamaya ihtiyacınız olabilir. Vartec'in cevabı, ileriye doğru bir yol önerir, ancak communicate
dikkatli kullanılmadıklarında çıkmazlara eğilimli olanlar dışındaki yöntemler .
Yukarıdaki tüm işlevlerde olduğu gibi, güvenlik bir endişe olmadığında, daha karmaşık kabuk komutlarını ileterek çalıştırabilirsiniz shell=True
.
notlar
1. Kabuk komutlarını çalıştırma: shell=True
argüman
Normal olarak, her bir çağrı run
, check_output
ya da Popen
yapıcı bir yürüten tek bir programı . Bu süslü bash tarzı borular anlamına gelmez. Karmaşık kabuk komutlarını çalıştırmak istiyorsanız, shell=True
her üç işlevin de desteklediği geçiş yapabilirsiniz .
Ancak bunu yapmak güvenlik endişelerini arttırır . Hafif komut dosyası oluşturmadan başka bir şey yapıyorsanız, her işlemi ayrı ayrı çağırmak ve her birinden çıktıyı bir girdi olarak diğerine,
run(cmd, [stdout=etc...], input=other_output)
Veya
Popen(cmd, [stdout=etc...]).communicate(other_output)
Boruları doğrudan bağlama cazibesi güçlüdür; direnmek. Aksi takdirde, büyük olasılıkla çıkmazları göreceksiniz veya bunun gibi hacky şeyler yapmak zorunda kalacaksınız .
2. Unicode ile ilgili düşünceler
check_output
Python 2'de bir dize, ancak bytes
Python 3'te bir nesne döndürür . Henüz yapmadıysanız unicode hakkında bilgi edinmek için biraz zaman ayırmaya değer .