Взаимодействие с Bash через Python без завершения - PullRequest
0 голосов
/ 11 октября 2019

Я пытаюсь создать процесс, который взаимодействует с оболочкой / bin / bash и получает информацию или выполняет команды. Я не хочу закрывать процесс, так как хочу сохранить состояние для будущих взаимодействий.

Я попытался найти решение для ответа SO , но процесс завершается после одного сеанса связи.

Проходя через Python subprocess API, я обнаружил, что subprocess.check_output() идеально подходит для этого. Однако, аналогично Popen.communicate(), это убивает процесс после одного выполнения.

Последний подход, который, кажется, работает, но небезопасен и приводит к взаимоблокировкам, использует Popen.stdin.write и Popen.stdout.read. Операция чтения переходит в бесконечное ожидание, если EOF не найден.

Есть ли более безопасный и простой способ добиться этого?

РЕДАКТИРОВАТЬ: Другие вещи, которые я пробовал:

import subprocess
import select
import os

process = subprocess.Popen(['/bin/bash'], shell=True, text=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
process.stdin.write('export SOMETHING=10000abc\n')
process.stdin.flush()
process.stdin.write('echo $SOMETHING\n')
process.stdin.flush()

r, w, e = select.select([process.stdout], [process.stdin], [], 0)
if process.stdout in r:
  print (os.read(process.stdout.fileno(), 50))
else:
  print ("Nothing to read")

Выход для этого всегда Nothing to read

1 Ответ

0 голосов
/ 11 октября 2019

Я закончил тем, что сделал следующее:

import subprocess
import select
import os

process = subprocess.Popen(['/bin/bash'], shell=True, text=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
process.stdin.write('export SOMETHING=10000abc\n')
process.stdin.flush()
process.stdin.write('echo $SOMETHING\n')
process.stdin.flush()

r, w, e = select.select([process.stdout], [process.stdin], [], 0.1)
result = ""
while process.stdout in r:
    result += os.read(process.stdout.fileno(), 100).decode("utf-8")
    r, w, e = select.select([process.stdout], [], [], 0.1)
process.kill()
print (result)
...