Python内からBitcoinで支払いをしようとしています。 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"}
)を取得するにはどうすればよいですか?
すべてのヒントを歓迎します!
subprocess.check_output()
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']
エラーテキストがstderrで報告される場合は、受け入れられたソリューションで処理できるとは思わない。私のテストから、例外の出力属性には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))
「ビットコインの残高よりも大きな額を送金する」ことは、予期しないエラーではありません。 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))
ここには良い答えがありますが、これらの答えには、スタックトレース出力からのテキストを思い付く答えがありません。これは例外のデフォルトの動作です。
そのフォーマットされたトレースバック情報を使用したい場合は、次のことができます。
import traceback
try:
check_call( args )
except CalledProcessError:
tb = traceback.format_exc()
tb = tb.replace(passwd, "******")
print(tb)
exit(1)
わかるかもしれませんが、上記の方法は、check_call(args)に表示したくないパスワードがある場合に役立ちます。