Почему этот вызов bash с python не работает?
Я немного борюсь с биткойнами. Когда я хочу получить некоторую информацию о локальной установке bitcoin, я просто запускаю 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 для Bitcoin, я просто хочу учиться делать это сам). Поэтому я сначала попробовал выполнить простую команду 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
и здесь я немного потерян. Кто-нибудь знает, что здесь не так? Все советы приветствуются!
[EDIT]
Используя превосходные ответы ниже, я теперь сделал следующую функцию, которая может пригодиться и для других. Он принимает либо строку, либо итерацию с отдельными аргументами, и анализирует вывод, если он 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
Ответы
Ответ 1
Либо используйте последовательность в аргументах:
process = subprocess.Popen(['bitcoin', 'getinfo'], stdout=subprocess.PIPE)
или установите для параметра shell
значение True
:
process = subprocess.Popen('bitcoin getinfo', stdout=subprocess.PIPE, shell=True)
Дополнительную информацию вы можете найти в документации:
args требуется для всех вызовов и должен быть строкой или последовательностью аргументов программы. Обычно предлагается последовательность аргументов, так как она позволяет модулю заботиться о любом требуемом экранировании и цитировании аргументов (например, разрешать пробелы в именах файлов). Если передать одну строку, либо оболочка должна быть True (см. Ниже), либо строка должна просто указывать исполняемую программу без указания каких-либо аргументов.
Ответ 2
используйте следующий код:
process = subprocess.Popen(['bitcoin', 'getinfo'], stdout=subprocess.PIPE)
вам не разрешено использовать пробелы для передачи параметров.