Bu sorunun cevabı kullandığınız Python sürümüne bağlıdır. En basit yaklaşım subprocess.check_outputiş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_outputyalnı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, runveya Popenbö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_outputfonksiyon 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 runişlev önerilir. subprocessModül için çok genel, yüksek düzeyli bir API sağlar . Bir programın çıktısını yakalamak için subprocess.PIPEbayrağı stdoutanahtar kelime değişkenine iletin. Ardından stdout, döndürülen CompletedProcessnesnenin ö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 bytesnesnedir, bu nedenle uygun bir dize istiyorsanız decodebuna 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 stdinbir bytesnesne inputiletin:
>>> 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.stdoutnormal çıktıyla birlikte yakalama ) ileterek yakalayabilirsiniz . Güvenlik endişe verici değilse, shell=Trueaş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 runsadece 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_outputiş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_outputsürümlerde run, check=Trueve ile çalışmak ve stdout=PIPEyalnızca stdoutöznitelik döndürmekle eşdeğerdir .
Sen geçebilir stderr=subprocess.STDOUTdöndü çıktıda yer aldığını hata iletileri sağlamak için - ama Python geçen bazı sürümlerinde stderr=subprocess.PIPEiçin check_outputteneke neden çözümsüzlüklerle . Güvenlik endişe verici değilse, shell=Trueaşağıdaki notlarda açıklandığı gibi ileterek daha karmaşık kabuk komutları da çalıştırabilirsiniz .
İşlemden boru hattına geçmeniz stderrveya işlemden check_outputgeçirmeniz gerekiyorsa, görev kadar olmayacaktır. Bkz Popenbu 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_outputsağladığınızdan daha karmaşık bir işlevsellik istiyorsanız, doğrudan Popenalt işlemler için düşük düzeyli API'yi içine alan nesnelerle çalışmanız gerekir .
PopenYapı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.splitdizeleri uygun şekilde biçimlendirilmiş listelerde ayrıştırmaya yardımcı olabilir. Popennesneler 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, communicateverileri 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, stderrve stdintüm PIPE(veya DEVNULL) almak için communicatehiç 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 communicatedikkatli 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=Trueargüman
Normal olarak, her bir çağrı run, check_outputya da Popenyapı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=Trueher üç 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_outputPython 2'de bir dize, ancak bytesPython 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 .