subprocess и psutil: как получить список из subprocess.check_output?

1

Я хочу определить текущее использование ЦП в кучу компьютеров Linux, все из которых доступны через SSH-соединение. На данный момент я что-то сделал с помощью модулей psutil и subprocess, но это могло быть намного проще, если бы я мог получить список из subprocess.check_output.

Поэтому я определил cpu_script.py:

import psutil

print(psutil.cpu_percent(interval=1,percpu=True))

для вызова в моем основном скрипте, который находится в той же папке, с:

import subprocess
import os
import numpy as np
import psutil

usr = "AA"
computer = "BB"
cpu_script = os.path.join(os.getcwd(),"cpu_script.py")
test = subprocess.check_output("ssh -X " + usr + "@" + computer + 
         "python3 -u - < " + cpu_script,shell=True).strip()

Поскольку выходы cpu_percent обычно входят в список, я бы ожидал, что моя "тестовая" переменная будет списком, но я действительно получаю байт:

input(test)
>> b'[4.0, 5.0, 7.0, 10.9, 18.4, 1.0, 4.0, 3.0]'
input(type(test))
>> <class 'bytes'>

Здесь мне удалось согнуть все, чтобы, наконец, получить массив (с расшифровкой + replace + np.fromstring), но он далек от удовлетворения:

tmp = test.decode("utf-8")
input(tmp)
>> [4.0, 5.0, 7.0, 10.9, 18.4, 1.0, 4.0, 3.0]
input(type(tmp))
>> <class 'str'>

tmp = (tmp.replace('[','')).replace(']','')
result = np.fromstring(tmp, sep=',')
input(result)
>> [ 4.   5.   7.  10.9 18.4  1.   4.   3. ]
input(type(result))
>> <class 'numpy.ndarray'>

Could'nt Я имею сразу переменную subprocess.check_output, которая представляет собой список или массив? Что мне не хватает?

Также, если есть способ избежать определения cpu_script, поэтому, чтобы передать непосредственно команду python в подпроцессе, мне было бы интересно! Я потерпел неудачу на всех моих попытках сделать это пока, сложная часть здесь заключается в том, что есть как ssh connexion, так и консольная команда python3, за которыми следуют команды python.

Спасибо за вашу помощь!

Теги:
python-3.x
ssh
subprocess
psutil

1 ответ

1
Лучший ответ

В основе программы python "сериализован" вывод как текст.

check_output возвращает объект bytes, который необходимо декодировать, затем "unserialize".

Я предлагаю:

import ast

result = ast.literal_eval(test.decode())

Лучшим способом было бы назвать этот скрипт суб-питона как модуль. В этом случае вам не пришлось бы запускать подпроцесс/сериализовать/несериализовать. Просто импортируйте подмодуль, вызовите функцию и получите реальный list. Конечно, в случае вызова подпроцесса ssh вы не можете.

Однако вы могли бы улучшить этот уродливый и check_output код-инъекцию вызова check_output требующего shell=True, передав файл-дескриптор открытого файла python для выполнения, подав вывод на вход check_output и используя список строк вместо строки как аргумент:

with open(cpu_script,"rb") as f:
    test = subprocess.check_output(["ssh","-X",usr + "@" + computer,"python3","-u","-"],stdin=f)

за которым следует код декодирования + оценки.

  • 0
    Большое спасибо, Ast часть отлично работает и позволяет мне получить список из "теста" в одну строку! Что касается остального, я боюсь, что я не понимаю, что вы предлагаете ... когда я заменяю script_cpu на fct_cpu() или даже прямо "psutil.cpu_percent(interval=1,percpu=True)" в моем вызове подпроцесса, Я получаю сообщение об ошибке: subprocess.CalledProcessError: Command 'ssh -X .... ' returned non-zero exit status 2
  • 0
    Я пропустил часть SSH. В этом случае вы должны придерживаться subprocess (ну, есть модуль paramiko , но я сомневаюсь, что он может запускать вызовы python изначально)
Показать ещё 6 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню