2014-07-20 43 views
26

Python'dan bir Bitcoin ödemesi yapmaya çalışıyorum. Bash ben normalde yapardı:Python subprocess.check_output() özel durum çıktısı nasıl alınır?

bitcoin sendtoaddress <bitcoin address> <amount> 

böylece örneğin:

bitcoin sendtoaddress 1HoCUcbK9RbVnuaGQwiyaJGGAG6xrTPC9y 1.4214 

ben çıktı olarak bir işlem kimliği almak ama başarılı olup olmadığını benim Bitcoin denge yüksek bir tutar daha büyük aktarmak çalışırsanız aşağıdaki gibi şimdi ödeme yapmaya çalışacağım benim Python programında

error: {"code":-4,"message":"Insufficient funds"} 

: Ben şu çıktıyı almak

import subprocess 

try: 
    output = subprocess.check_output(['bitcoin', 'sendtoaddress', address, str(amount)]) 
except: 
    print "Unexpected error:", sys.exc_info() 

yeterli bakiye varsa iyi çalışıyor, ancak yeterli bakiye bunu sys.exc_info() baskılar varsa:

(<class 'subprocess.CalledProcessError'>, CalledProcessError(), <traceback object at 0x7f339599ac68>) 

Muhtemelen şu an komut satırında olsun hata içermez. Yani sorum şu; Çıktı hatalarını ({"code":-4,"message":"Insufficient funds"}) Python'dan nasıl alabilirim?

Tüm ipuçları kabul edilir!

+1

Cevaplardan birini kabul etmek ister misiniz? – maxschlepzig

cevap

41

subprocess.check_output() docs göre, hata kaldırdı istisnası hata ayrıntılarını erişmek için kullanabileceği bir output niteliği vardır:

try: 
    subprocess.check_output(...) 
except subprocess.CalledProcessError as e: 
    print e.output 
Daha sonra bu dizeyi analiz etmek ve birlikte hata ayrıntılarını ayrıştırmak gerekir

json modülü: "benim Bitcoin denge yüksek bir tutar daha büyük transferi" çalışılıyor

if e.output.startswith('error: {'): 
    error = json.loads(e.output[7:]) # Skip "error: " 
    print error['code'] 
    print error['message'] 
+0

Stdout'a bir şey çıkaran ve sonra 1 döndüren bir program arıyorum, ancak check_output onu yakalamıyor – JorgeeFG

+0

@JorgeeFG Sonra programınızda yanlış bir şey var. Yorum bölümünün yeni sorular sormak için doğru yer olmadığını lütfen unutmayın. Sorununuzla ilgili yardıma ihtiyacınız varsa, sayfanın sağ üst tarafındaki büyük "Soru Sor" düğmesini tıklayın. –

+0

Not, bu Python 2.6 veya daha düşük bir sürümü ile çalışmaz! – whirlwin

5

beklenmeyen bir hata değildir. Sen gereksiz yere bir özel durum önlemek için yerine doğrudan check_output() ait Popen.communicate() kullanabilirsiniz:

from subprocess import Popen, PIPE 

p = Popen(['bitcoin', 'sendtoaddress', ..], stdout=PIPE) 
output = p.communicate()[0] 
if p.returncode != 0: 
    print("bitcoin failed %d %s" % (p.returncode, output)) 
+0

Python, bir EAFP programlama stilini (izin almaktan af dilemek için daha kolay) teşvik eder, bu gibi durumlarda 'if' kontrolleri üzerinden istisna işlemlerini tercih eder. –

+5

@FerdinandBeyer: Bu durumda EAFP geçerli değildir: Aksi takdirde yapamayacağınız bir çağrı yapmıyorsunuz. Kod, LBYL yapısına sahip değildir: 'eğer kontrol et(): do()' ile değiştirmiş olsaydınız, EAFP 'nin yerine şunu yazabilirsiniz: do() Hata: handle_error()' dışında. Cevapdaki kod, check_output() işlevini inline eder ve "p.returncode" dalında sadece bir seviyeyi yakalamak için bir istisnayı kaldırmayı önler. Kargo kült programlamadan kaçının, düşünün – jfs

14

Kabul çözüm hata metni, standart hataya bildirilmektedir durumda işler sanmıyorum. Testlerimden istisnanın çıktı niteliği stderr'in sonuçlarını içermedi ve dokümanlar check_output() 'da stderr = PIPE kullanarak uyardı. Bunun yerine, J.F Sebastian'ın çözümüne stderr desteği ekleyerek küçük bir iyileştirme önerebilirim. Her şeyden öte, hatalarla uğraşmaya çalışıyoruz ve stderr sık ​​sık bildirildikleri yer. İyi cevaplar var burada

from subprocess import Popen, PIPE 

p = Popen(['bitcoin', 'sendtoaddress', ..], stdout=PIPE, stderr=PIPE) 
output, error = p.communicate() 
if p.returncode != 0: 
    print("bitcoin failed %d %s %s" % (p.returncode, output, error)) 
+0

'stderr' çıktısının burada çok alakalı olduğunu kabul ediyorum. Bunun yerine alternatif bir çözüm 'run()' işlevini kullanmaktır (bkz. [Check_output docs] (https://docs.python.org/3/library/subprocess.html#subprocess.check_output) nasıl değiştirilir). Çünkü hata raporlama işleminde istisnadan "e.stderr" kullanabilirsiniz. – Sebastian

+0

Bu en üstünde olmalıdır. – Oleg

2

, ancak bu cevaplar içinde, bir istisna varsayılan davranıştır yığın-iz çıkışı, gelen metin ile çıkageldi bir cevap olmamıştır. Bunu biçimlendirilmiş traceback bilgisini kullanmak isterseniz

, sen isteyebilirsiniz:

sen söylemek mümkün olabilir gibi
import traceback 

try: 
    check_call(args) 
except CalledProcessError: 
    tb = traceback.format_exc() 
    tb = tb.replace(passwd, "******") 
    print(tb) 
    exit(1) 

, yukarıdaki durumda check_call bir şifreye sahip yararlıdır (args) görüntülemeyi engellemek istediğiniz

İlgili konular