Why does this bash call from python not work?

I am messing around with Bitcoins a bit. When I want to get some info about the local bitcoin install, I simply run bitcoin getinfo and I get something like this:

{
    "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" : ""
}

I now want to do this call from within Python (before anyone points it out; I know there are Python implementations for Bitcoin, I just want to learn doing it myself). So I first tried executing a simple ls command like this:

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

This works fine, printing out the list of files and folders as expected. So then I did this:

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

but this gives the following error:

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

and here I'm kinda lost. Does anybody know what's wrong here? All tips are welcome!

[EDIT] Using the excellent answers below I now made the following function, which might come in handy for others as well. It takes either a string, or an iterable with separate arguments and parses the output if it is 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

Either use a sequence in arguments:

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

or set the shell parameter to True :

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

You can find more information in the documentation:

args is required for all calls and should be a string, or a sequence of program arguments. Providing a sequence of arguments is generally preferred, as it allows the module to take care of any required escaping and quoting of arguments (eg to permit spaces in file names). If passing a single string, either shell must be True (see below) or else the string must simply name the program to be executed without specifying any arguments.


use the following code:

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

you are not allowed to use spaces for passing parameters.

链接地址: http://www.djcxy.com/p/25330.html

上一篇: 如何在Android中创建可重用的活动?

下一篇: 为什么这个python的python调用不起作用?