为什么这个来自 python 的 bash 调用不起作用?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24340877/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 10:43:43  来源:igfitidea点击:

Why does this bash call from python not work?

pythonbashsubprocessbitcoin

提问by kramer65

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

我有点搞砸了比特币。当我想获取有关本地比特币安装的一些信息时,我只需运行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" : ""
}

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 lscommand like this:

我现在想从 Python 内部进行这个调用(在任何人指出之前;我知道比特币Python 实现,我只想学习自己做)。所以我首先尝试执行一个ls像这样的简单命令:

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:

[编辑] 使用下面的优秀答案,我现在制作了以下功能,这对其他人也可能派上用场。它接受一个字符串,或者一个带有单独参数的可迭代对象,如果它是 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

回答by Gergo Erdosi

Either use a sequence in arguments:

在参数中使用序列:

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

or set the shellparameter to True:

或将shell参数设置为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 (e.g. 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.

所有调用都需要 args 并且应该是字符串或程序参数序列。提供一系列参数通常是首选,因为它允许模块处理任何所需的参数转义和引用(例如,允许文件名中的空格)。如果传递单个字符串,则 shell 必须为 True(见下文),否则字符串必须简单地命名要执行的程序而不指定任何参数。

回答by Gergo Erdosi

use the following code:

使用以下代码:

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

you are not allowed to use spaces for passing parameters.

不允许使用空格来传递参数。