Как написать в подпроцесс Python 'stdin?
Я пытаюсь написать Python script, который запускает подпроцесс и записывает в подпроцесс stdin. Я также хотел бы определить действие, которое нужно предпринять, если подпроцесс сработает.
Процесс, который я пытаюсь запустить, - это программа под названием nuke
, у которой есть своя встроенная версия Python, которую я хотел бы отправлять командам, а затем сказать, что она прекратит работу после команд выполнить. До сих пор я решил, что если я запустил Python в командной строке, а затем запустил nuke
в качестве подпроцесса, тогда я могу ввести команды в nuke
, но я бы хотел, чтобы это все a script, чтобы мастер-программа Python могла запускать nuke
, а затем записывать в свой стандартный ввод (и, следовательно, в свою встроенную версию Python) и расскажите, как это сделать, и я написал script, который запускает nuke
следующим образом:
subprocess.call(["C:/Program Files/Nuke6.3v5/Nuke6.3", "-t", "E:/NukeTest/test.nk"])
Тогда ничего не происходит, потому что nuke
ждет ввода пользователя. Как мне теперь написать стандартный ввод?
Я делаю это, потому что я запускаю плагин с nuke
, который заставляет его периодически прерываться при рендеринге нескольких кадров. Поэтому я хотел бы, чтобы этот script мог запустить nuke
, сказать ему что-то сделать, а затем, если он сработает, попробуйте еще раз. Поэтому, если есть способ поймать сбой и все равно быть в порядке, это было бы здорово.
Ответы
Ответ 1
Лучше использовать communicate
:
from subprocess import Popen, PIPE, STDOUT
p = Popen(['myapp'], stdout=PIPE, stdin=PIPE, stderr=PIPE)
stdout_data = p.communicate(input='data_to_write')[0]
"Лучше" из-за этого предупреждения:
Используйте функцию связи(), а не .stdin.write,.stdout.read или .stderr.read, чтобы избежать взаимоблокировок из-за того, что любой из других буферов буферов ОС заполняет и блокирует дочерний процесс.
Ответ 2
Вы можете предоставить файл-подобный объект аргументу stdin
subprocess.call()
.
Здесь документация для объекта Popen
.
Чтобы захватить вывод, вместо этого вы должны использовать subprocess.check_output()
, который принимает аналогичные аргументы. Из документации:
>>> subprocess.check_output(
... "ls non_existent_file; exit 0",
... stderr=subprocess.STDOUT,
... shell=True)
'ls: non_existent_file: No such file or directory\n'
Ответ 3
Вот как это выглядит для коммерческой версии NUKE 11.3v4 на Windows 10
:
import subprocess
# Run NUKE script in Terminal mode on Windows machine...
subprocess.Popen(['C:/Program Files/Nuke11.3v4/Nuke11.3.exe', '-t', 'E:/NukeTest/test.nk'], stdin=PIPE, stdout=PIPE)
Вот как это работает для некоммерческой версии NUKE 11.3v4 на macOS 10.14
:
import subprocess
from subprocess import Popen, PIPE
import time
# Run NUKE script in Terminal mode on MacOS machine...
np = subprocess.Popen(['/Applications/Nuke11.3v4/NukeX11.3v4 Non-commercial.app/NukeX11.3v4 Non-commercial', '-t', '/Users/<username>/Desktop/test.nknc'], stdin=PIPE, stdout=PIPE)
# Choose a method to wait for the subprocess to finish...
np.wait()
time.sleep(5)
data = np.communicate(input='data')[0]
print(data)
Результат выглядит следующим образом:
'''
NukeX 11.3v4, 64 bit, built May 1 2019.
Copyright (c) 2019 The Foundry Visionmongers Ltd. All Rights Reserved.
Non-commercial mode active.
Licence expires on: 2019/7/27
(11, 3, 4)
('darwin', 'posix')
/Applications/Nuke11.3v4/Nuke11.3v4.app/Contents/MacOS/../Frameworks/Python.framework/Versions/Current/
Disk cache /var/tmp/nuke-u501/ViewerCache/??: 424MB (5% of 10240MB) used in 81 files.
'''
Также вы можете запустить подпроцесс в графическом интерфейсе, используя флаг -v
для изображений:
subprocess.Popen(['C:/Program Files/Nuke11.3v4/Nuke11.3.exe', '-v', 'E:/NukeTestImages/image.exr'], stdin=PIPE, stdout=PIPE)
Надеюсь это поможет.
Ответ 4
from subprocess import Popen, PIPE, STDOUT
p = Popen(['myapp'], stdout=PIPE, stdin=PIPE, stderr=PIPE)
stdout_data = p.communicate(input='data_to_write')[0]
работает только в том случае, если "myapp" не принимает аргументов.