Форум русскоязычного сообщества Ubuntu


Считаете, что Ubuntu недостаточно дружелюбна к новичкам?
Помогите создать новое Руководство для новичков!

Автор Тема: Получение вывода внешнего процесса в Питоне  (Прочитано 3789 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн Sly_tom_cat

  • Don't worry, be happy!
  • Заслуженный пользователь
  • Старожил
  • *
  • Сообщений: 12130
  • Xubuntu 22.04
    • Просмотр профиля
    • Github
Не совсем понял что вы сказали.

Сам не пробовал, но попробывал бы так - делаю два потока, в одном запускаю подпроцесс а во втором (после ожидания) шлю в pipe подпроцесса нужные коды. После чего можно джоинить потоки (дождавшить завершения подпроцесса) и обрабатывать результаты.
Индикатор для Yandex-Disk: https://forum.ubuntu.ru/index.php?topic=241992
UEFI-Boot - грузимся без загрузчика: https://help.ubuntu.ru/wiki/uefiboot

Оффлайн .ubuntufan

  • Активист
  • *
  • Сообщений: 638
    • Просмотр профиля
Цитировать
В принципе ctrl-c можно процессу и послать через открытый пайп для общения с ним, но для этого нужен уже отдельный поток (т.к. тот поток, что запустит выполнение внешнего процесса будет занят).

не обязательно нужен отдельный поток

Код: (Python) [Выделить]
#!/usr/bin/env python2

import subprocess
import io

p = subprocess.Popen(["sh", "./some.sh"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False)
f = io.open(p.stdout.fileno(), 'rb', closefd=False)
buf = ''
while True:
buf += f.read1(4096)
if len(buf) > 8192:
p.terminate()
f.close()
break
print buf

Условие len(buf) > 8192 просто в качестве примера, когда посылать SIGTERM

Оффлайн Luca Brasi

  • Автор темы
  • Активист
  • *
  • Сообщений: 706
  • typical engineer
    • Просмотр профиля
.ubuntufan, error типа "Can't convert 'bytes' object to str implicitly". Это как я понимаю нельзя разные  типы объединять, как быть...
Считывать по 4096 байт, это ведь произвольное число или с тайным смыслом?
Ubuntu 18.04/ AMD Ryzen 5 2600 3.4GHz/ MSI B450-A Pro Max / Crucial DDR4-3000 16384MB / MSI PCI-Ex GeForce GT 710 2048 MB / Chieftec GPS-600

Оффлайн Sly_tom_cat

  • Don't worry, be happy!
  • Заслуженный пользователь
  • Старожил
  • *
  • Сообщений: 12130
  • Xubuntu 22.04
    • Просмотр профиля
    • Github
Luca Brasi, вы похоже Python3 используете раз там рукается на неявное преобразование байтов в строки (в 2.7 это вроде проходит без ругани)

В Python3 надо явно указывать кодировку вызывая метод decode
Код: (python) [Выделить]
bytes.decode('<кодировка>')
Индикатор для Yandex-Disk: https://forum.ubuntu.ru/index.php?topic=241992
UEFI-Boot - грузимся без загрузчика: https://help.ubuntu.ru/wiki/uefiboot

Оффлайн Luca Brasi

  • Автор темы
  • Активист
  • *
  • Сообщений: 706
  • typical engineer
    • Просмотр профиля
Sly_tom_cat, указал явно кодировку - заработало)
Ubuntu 18.04/ AMD Ryzen 5 2600 3.4GHz/ MSI B450-A Pro Max / Crucial DDR4-3000 16384MB / MSI PCI-Ex GeForce GT 710 2048 MB / Chieftec GPS-600

Оффлайн Sly_tom_cat

  • Don't worry, be happy!
  • Заслуженный пользователь
  • Старожил
  • *
  • Сообщений: 12130
  • Xubuntu 22.04
    • Просмотр профиля
    • Github
Еще вариант: указать буферу байтовый тип, т.е.
Код: (python) [Выделить]
buf = b''Это вполне можно сделать если потом обрабатывать считанное как байты или можно потом, разом, все преобразовать в строку с указанием кодировки.

Там ругань у вас была именно потому что buf = '' - определяет buf как строку с кодировкой по умолчанию (если не переопределяли то utf-8), а поток чтения открыт как байтовый (опции открытия 'rb' - это чтение и байты).

Можно было (еще один вариант) открыть поток на чтение как текст (опция 'rt') и тогда read будет выдавать строку (опять все пройдет гладко в python3).
« Последнее редактирование: 01 Апреля 2015, 22:49:48 от Sly_tom_cat »
Индикатор для Yandex-Disk: https://forum.ubuntu.ru/index.php?topic=241992
UEFI-Boot - грузимся без загрузчика: https://help.ubuntu.ru/wiki/uefiboot

Оффлайн Luca Brasi

  • Автор темы
  • Активист
  • *
  • Сообщений: 706
  • typical engineer
    • Просмотр профиля
Sly_tom_cat, я тут почитал про потоки в Питоне (раньше с этим в принципе не сталкивался) и пытаюсь переварить ранее сказанное вами.
Цитировать
делаю два потока, в одном запускаю подпроцесс а во втором (после ожидания) шлю в pipe подпроцесса нужные коды. После чего можно джоинить потоки (дождавшить завершения подпроцесса)

Т.е. " ctrl-c" или другое что то, в каком виде отсылать?
Код: (Python) [Выделить]
subprocess.Popen (["echo","^C"],stdin=subprocess.PIPE, stderr=subprocess.PIPE, shell=False)
Ubuntu 18.04/ AMD Ryzen 5 2600 3.4GHz/ MSI B450-A Pro Max / Crucial DDR4-3000 16384MB / MSI PCI-Ex GeForce GT 710 2048 MB / Chieftec GPS-600

Оффлайн Sly_tom_cat

  • Don't worry, be happy!
  • Заслуженный пользователь
  • Старожил
  • *
  • Сообщений: 12130
  • Xubuntu 22.04
    • Просмотр профиля
    • Github
Luca Brasi, не не стоит с потоками для такой задачи заморачиваться как я предполагал. .ubuntufan гораздо более правильный вариант предложил.
 
Потоки в большей степени нужны для распараллеливания задач с целью повышения производительности.

(Нажмите, чтобы показать/скрыть)
« Последнее редактирование: 03 Апреля 2015, 01:40:42 от Sly_tom_cat »
Индикатор для Yandex-Disk: https://forum.ubuntu.ru/index.php?topic=241992
UEFI-Boot - грузимся без загрузчика: https://help.ubuntu.ru/wiki/uefiboot

Оффлайн Luca Brasi

  • Автор темы
  • Активист
  • *
  • Сообщений: 706
  • typical engineer
    • Просмотр профиля
в некоторых статьях мне попадалось мнение, что потоки в питоне не очень увлекательны... Судя из вашего примера это не так :).
Хорошо. Но тем менее мне не все ясно. Прервать процесс можно через метод terminate() . Но как быть если что то нужно запустить из под рута, дождаться запроса пароля... А как его подсунуть?
Ubuntu 18.04/ AMD Ryzen 5 2600 3.4GHz/ MSI B450-A Pro Max / Crucial DDR4-3000 16384MB / MSI PCI-Ex GeForce GT 710 2048 MB / Chieftec GPS-600

Оффлайн Sly_tom_cat

  • Don't worry, be happy!
  • Заслуженный пользователь
  • Старожил
  • *
  • Сообщений: 12130
  • Xubuntu 22.04
    • Просмотр профиля
    • Github
Luca Brasi, у вас каждый раз новые вводные.... :idiot2:

По идее метод работы с потоками открытого приложения который показал .ubuntufan - может быть расширен. Просто откройте еще p.stdin.fileno() как поток на запись. Тогда после запуска можно читать из выходного потока пока не получите приглашение ввода пароля и передать его во входной поток приложения.

Но мне кажется, что это как-то неправильно. Наверное есть какие-то другие способы поднятия приоритета процесса/ смены владельца. Надо посмотреть, что там в стандартных библиотеках есть на эту тему - сам я с такой задачей не сталкивался и ничего определенного сказать не могу.


По поводу потоков - они не панацея и реально помогают порой в довольно узкой категории задач. В том же моем примере, наиболее длительным процессом является получение ответа от сервера. И именно за счет отправки на сервер одновременно 30-40 асинхронных запросов появляется возможность в десятки раз сократить время решения задачи.

А кроме того там ведь у меня 12-14 потоков пробовали байты из заранее подготовленных и не пересекающихся множеств и первый из процессов, который находил соответствие, формировал сигнал после которого остальные процессы завершались не заканчивая проверку своего набора. Тем самым еще и количество запросов сокращается по сравнению с чисто последовательным выполнением.

Если вам интересно - могу прислать вам код этого домашнего задания (хотя наверное к нему придется дать кучу пояснений, несмотря на множество комментариев по тексту). Просто мне показалось это наверное самая идеальная задача для демонстрации многопоточности.
« Последнее редактирование: 03 Апреля 2015, 11:03:18 от Sly_tom_cat »
Индикатор для Yandex-Disk: https://forum.ubuntu.ru/index.php?topic=241992
UEFI-Boot - грузимся без загрузчика: https://help.ubuntu.ru/wiki/uefiboot

Оффлайн Luca Brasi

  • Автор темы
  • Активист
  • *
  • Сообщений: 706
  • typical engineer
    • Просмотр профиля
ясно. Будет интересно глянуть на ваш код
Ubuntu 18.04/ AMD Ryzen 5 2600 3.4GHz/ MSI B450-A Pro Max / Crucial DDR4-3000 16384MB / MSI PCI-Ex GeForce GT 710 2048 MB / Chieftec GPS-600

Оффлайн Sly_tom_cat

  • Don't worry, be happy!
  • Заслуженный пользователь
  • Старожил
  • *
  • Сообщений: 12130
  • Xubuntu 22.04
    • Просмотр профиля
    • Github
Luca Brasi, оправил вам с пояснениями на мыло указанное в профиле на форуме.
Индикатор для Yandex-Disk: https://forum.ubuntu.ru/index.php?topic=241992
UEFI-Boot - грузимся без загрузчика: https://help.ubuntu.ru/wiki/uefiboot

 

Страница сгенерирована за 0.046 секунд. Запросов: 25.