#python
#python
Вопрос:
В настоящее время я пытаюсь написать скрипт на python, который, помимо многих других вещей, вызывает исполняемый файл и сохраняет то, что этот исполняемый файл отправляет в стандартный вывод, в переменной. Вот что у меня есть:
1 #!/usr/bin/python
2 import subprocess
3
4 subprocess.call("./pmm", shell=True)
Как бы я мог сохранить выходные данные pmm в переменной?
Ответ №1:
В Python 2.7 (и 3.1 или выше) вы можете использовать subprocess.check_output()
. Пример из документации:
>>> subprocess.check_output(["ls", "-l", "/dev/null"])
'crw-rw-rw- 1 root root 1, 3 Oct 18 2007 /dev/nulln'
Ответ №2:
p = subprocess.Popen(["./pmm"], shell=False, stdout=subprocess.PIPE)
output = p.stdout.read()
Комментарии:
1. Это может привести к взаимоблокировке, если процесс выдает много выходных данных. Используйте
p.communicate()
вместоp.stdout.read()
. (Смотрите Документы — прокрутите немного вверх.)2. это не имеет особого смысла, поскольку включено предупреждение о взаимоблокировке
p.wait()
(как будто при заполнении выходного буфера процесс будет ждать, пока в нем не освободится место, таким образом, мертвая блокировка, если процесс чтения ожидает его), неp.stdout.read()
который, какp.communicate()
, завершится неудачей, если выходные данные будут большими или неограниченными, и в этом случае было бы лучше читать порциями.3. @Dan D: Предупреждение находится непосредственно над документацией
Popen.stdout
и гласит «Используйтеcommunicate()
вместо.stdin.write
,.stdout.read
или.stderr.read
чтобы избежать взаимоблокировок […]».4. Если подумать, это не приведет к тупиковой ситуации, если процесс выдает много выходных данных в stdout , а скорее, если в stderr много выходных данных для заполнения буфера файлового дескриптора, который не читается.
5. да, но если вы не записываете в
p.stdin
, а только читаете изp.stdout
, взаимоблокировки быть не может.
Ответ №3:
Я написал сообщение об этом некоторое время назад:
http://trifoliummedium.blogspot.com/2010/12/running-command-line-with-python-and.html
Используйте p.communicate(), чтобы получить как stdout, так и stderr
Ответ №4:
Сначала вы должны сохранить ссылку на подпроцесс (привязать его к имени … что на других языках и более неформально называется «присвоение ее переменной»). Итак, вы должны использовать что-то вроде proc = subprocess.Popen(...)
Оттуда я рекомендую вам вызвать proc.poll()
, чтобы проверить, завершилась ли программа, и либо перейти в режим ожидания (например, используя time.sleep()
функцию), либо выполнить другую работу (например, используя select.select()
), а затем проверить еще раз, позже. Или вы можете вызвать proc.wait()
, чтобы убедиться, что команда this ./pmm завершила свою работу, прежде чем ваша программа продолжит. poll()
Метод экземпляра подпроцесса вернет «None», если подпроцесс все еще запущен; в противном случае он вернет значение завершения команды, которая выполнялась в этом подпроцессе. wait()
Метод для подпроцесса приведет к блокировке вашей программы, а затем вернет значение exit.
После этого вы можете вызвать (output, errormsgs) = proc.communicate()
для захвата любых выходных данных или сообщений об ошибках из вашего подпроцесса. Если выходные данные слишком велики, это может вызвать проблемы; использование экземпляра процесса .stdout
(дескриптор файла канала) сложно, и, если вы собираетесь попробовать это, вам следует использовать функции в fcntl
модуле (управление файловыми дескрипторами), чтобы переключить его в неблокирующий режим и быть готовым обрабатывать исключения, возникающие при попытке read()
вызвать буфер, когда он пуст.
Комментарии:
1.
proc.communicate()
также ожидает завершения дочернего процесса; поэтому, если вы не планируете делать что-либо еще тем временем, вы можете вызвать .communicate напрямую.