如何从Python subprocess.check_output()捕获异常输出?

2024-04-24 23:20:26 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试从Python内部进行比特币支付。在bash中,我通常会这样做:

bitcoin sendtoaddress <bitcoin address> <amount>

例如:

bitcoin sendtoaddress 1HoCUcbK9RbVnuaGQwiyaJGGAG6xrTPC9y 1.4214

如果成功,我将获得一个事务id作为输出,但如果我尝试转移的金额大于我的比特币余额,我将获得以下输出:

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

在Python程序中,我现在尝试按如下方式付款:

import subprocess

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

如果有足够的平衡,它可以正常工作,但是如果没有足够的平衡sys.exc_info()则打印出:

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

它不包括我在命令行上得到的错误。所以我的问题是:如何从Python中获取输出的错误({"code":-4,"message":"Insufficient funds"})?

欢迎所有小费!


Tags: infomessageoutputaddresssyscodeerroramount
3条回答

尝试“转移比我的比特币余额大的金额”并不是一个意外的错误。您可以直接使用Popen.communicate()而不是check_output()来避免不必要地引发异常:

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))

我认为接受的解决方案不能处理stderr上报告错误文本的情况。从我的测试来看,异常的output属性不包含stderr的结果,文档警告不要在check_output()中使用stderr=PIPE。相反,我建议通过添加stderr支持对J.F Sebastian的解决方案进行一个小的改进。毕竟,我们试图处理错误,而stderr是经常报告错误的地方。

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))

根据^{} docs,错误时引发的异常有一个output属性,您可以使用该属性访问错误详细信息:

try:
    subprocess.check_output(...)
except subprocess.CalledProcessError as e:
    print(e.output)

然后,您应该能够分析该字符串并使用json模块分析错误详细信息:

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

相关问题 更多 >