Python, выполнить шелл-код в отдельном процессе и получить ответ
3дpacтвуйте, вообщем идея такова: выполнить шелл-код в отдельном процессе и получить ответ. Я уверен что данный вопрос является дубликатом, но я не могу найти код.
Я пробовал реализовать это таким образом:
import subprocess, multiprocessing
def test(_command, _out_func):
process= subprocess.Popen(_command, stdout=subprocess.PIPE, stdin= subprocess.PIPE, shell= True, close_fds=True)
if _out_func: _out_func( _command, process.communicate()[0].decode() )
def run_command(command, out_func= None):
process = multiprocessing.Process(target=test, args=([command, out_func]))
process.start()
def o(command, output): print(command, ">", output, sep='')
run_command("python -c 'print(1)'", o)
#while 1: print(5)
Функция run_command принимает команду в качестве строки и функцию которая будет выполнена если нужно вернуть ответ от шелл-кода. Если функция вывода указана, то run_command будет ожидать ответа от шелл кода, а если функция не указана, то шелл код просто выполняется в отдельном процессе не ожидая вывода.
Проблема в том что если не указать функцию для вывода, то есть просто вызвать run_command("echo 1"), то выходит ошибка
sh: write error: Broken pipe
[Program finished]
Я понимаю что она связана с тем что основной процесс завершился, а subprocess.Popen пытается вернуть ответ в несуществующий процесс. Это и есть место на котором я застрял.
Как можно выполнить шелл-код и получить ответ, игнорируя BrokenPipeError: [Errno 32] Broken pipe?
Ответы (1 шт):
import subprocess, threading
def test(*command):
with subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, shell=True) as proc:
yield from proc.stdout
def run_command(*command, out_func=None):
gen = test(*command)
if out_func:
return out_func(command, gen)
else:
def _out():
for _ in gen: continue
print(f'воход из потока {command}')
threading.Thread(target=_out, daemon=False).start()
def out(command, output):
print(command)
for chunk in output:
print(chunk.decode('cp866', 'ignore'))
run_command('python', '-c', 'print(1)', out_func=out)
run_command('echo', '1', out_func=out)
run_command('ping', '127.0.0.1')
print("выход из __main__, до завершения run_command('ping', '127.0.0.1')")
out:
('python', '-c', 'print(1)')
1
('echo', '1')
1
выход из __main__, до завершения run_command('ping', '127.0.0.1')
воход из потока ('ping', '127.0.0.1')