为什么这个来自Python的bash调用不工作?

2 投票
2 回答
9398 浏览
提问于 2025-04-18 10:36

我最近在玩比特币。当我想获取本地比特币安装的一些信息时,我只需运行 bitcoin getinfo,然后就能得到类似这样的信息:

{
    "version" : 90100,
    "protocolversion" : 70002,
    "walletversion" : 60000,
    "balance" : 0.00767000,
    "blocks" : 306984,
    "timeoffset" : 0,
    "connections" : 61,
    "proxy" : "",
    "difficulty" : 13462580114.52533913,
    "testnet" : false,
    "keypoololdest" : 1394108331,
    "keypoolsize" : 101,
    "paytxfee" : 0.00000000,
    "errors" : ""
}

现在我想在Python里面调用这个命令(在有人提醒之前,我知道有 比特币的Python实现,但我只是想自己学着做)。所以我首先尝试执行一个简单的 ls 命令,像这样:

import subprocess
process = subprocess.Popen('ls', stdout=subprocess.PIPE)
output = process.communicate()[0]
print output

这个命令运行得很好,按预期打印出了文件和文件夹的列表。然后我做了这个:

import subprocess
process = subprocess.Popen('bitcoin getinfo', stdout=subprocess.PIPE)
output = process.communicate()[0]
print output

但这给出了以下错误:

Traceback (most recent call last):
  File "testCommandLineCommands.py", line 2, in <module>
    process = subprocess.Popen('bitcoin getinfo', stdout=subprocess.PIPE)
  File "/usr/lib/python2.7/subprocess.py", line 710, in __init__
    errread, errwrite)
  File "/usr/lib/python2.7/subprocess.py", line 1327, in _execute_child
    raise child_exception
OSError: [Errno 2] No such file or directory

在这里我有点迷茫。有没有人知道这里出了什么问题?欢迎任何建议!

[编辑] 使用下面的优秀回答,我现在做了一个函数,这个函数可能对其他人也有帮助。它可以接受一个字符串,或者一个可迭代的多个参数,并在输出是json格式时进行解析:

def doCommandLineCommand(command):
    process = subprocess.Popen(command, stdout=subprocess.PIPE, shell=isinstance(command, str))
    output = process.communicate()[0]
    try:
        return json.loads(output)
    except ValueError:
        return output

2 个回答

4

使用以下代码:

process = subprocess.Popen(['bitcoin', 'getinfo'], stdout=subprocess.PIPE)

在传递参数时,不允许使用空格。

10

你可以在参数中使用一个序列:

process = subprocess.Popen(['bitcoin', 'getinfo'], stdout=subprocess.PIPE)

或者把 shell 参数设置为 True

process = subprocess.Popen('bitcoin getinfo', stdout=subprocess.PIPE, shell=True)

你可以在这个 文档 中找到更多信息:

在所有调用中,args 是必需的,它应该是一个字符串,或者是一组程序参数。一般来说,提供一组参数是更好的选择,因为这样可以让模块自动处理参数中的转义和引号问题(比如允许文件名中有空格)。如果你只传递一个字符串,那么要么 shell 必须设置为 True(见下文),要么这个字符串只能是要执行的程序的名称,而不能指定任何参数。

撰写回答