2017-01-14 3 views
3

У меня есть код Python, который я хочу отлаживать с помощью perf. Для этого я хочу использовать подпроцесс. Следующая команда возвращает информацию о процессе, относящуюся к процедуре, до тех пор, пока команда не выйдет через Ctrl^C.Подпроцесс Python работает в фоновом режиме перед возвратом вывода

perf stat -p <my_pid> 

Теперь я хочу, чтобы запустить это внутри кода Python в фоновом режиме, пока какой-то момент, когда я хочу, чтобы иметь возможность завершить свою работу и печать вывода команды. Для того, чтобы показать, что я имею в виду:

x = subprocess.call(["perf","stat","-p",str(GetMyProcessID())]) 

.. CODE TO DEBUG .. 

print x # I want to terminate subprocess here and output 'x' 

Теперь я хочу, чтобы определить, что делать в строке «печати х» для завершения процесса и проверьте вывод. Любая идея/помощь приветствуются.

Приветствия и спасибо заранее,

ответ

1

Во-первых: я советую против вызова perf из вашего процесса питона (как вы видите сложности ниже задачи), но вместо того, чтобы использовать это из командной строки:

sudo perf stat -- python test.py 

Если вы действительно хотите позвонить Perf внутри питона, то вы будете сталкиваться с некоторыми сложными проблемами:

  1. прекратить perf и сделать его выход собранных статистик производительности вы должны послать ему SIGINT сигнала (попробуйте с sudo perf stat -p mypid: ctrl-\ не будет печатать ничего, тогда как ctrl-c будет)
  2. вам нужно захватить stderr, как перфорация посылает свой вывод до stderr (по крайней мере, в моей версии)
  3. вам необходимо использовать fork() с одним процессом отправки SIGINT, а другое чтение - при выводе процесса. Без вилок это не сработает, потому что после того, как вы SIGINT отредактировали процесс , вы больше не можете читать из stdin по мере того, как процесс уже ушел, а когда вы читаете от stdin, сначала вы не получите никакого вывода до тех пор, пока perf не будет правильно завершен.

Это означает, что вы в конечном итоге с этой питона программы:

import subprocess 
import os 
import signal 
import time 

perf = subprocess.Popen(['perf', 'stat', '-p', str(os.getpid())], stderr=subprocess.PIPE) 

# <-- your code goes here 

if os.fork() == 0: 
    # child 
    time.sleep(1) # wait until parent runs `stderr.read()` 
    perf.send_signal(signal.SIGINT) 
    exit(0) 

# parent 
print("got perf stats>>{}<<".format(perf.stderr.read().decode("utf-8"))) 

time.sleep(1) немного некрасиво, что она делает это, что это будет, но я предполагаю, что это будет делать трюк для 99% случаев. Это почти не влияет на первичную информацию, единственное влияние, которое она оказывает на «общее время выполнения» (*xx seconds time elapsed)

+0

Это похоже на то, что он действительно близок к тому, что я хочу. Один вопрос: поскольку перфомант динамически производит статистику, любая задержка в системе, такая как time.sleep, увеличивает количество команд (следовательно, ошибок) на выходе. Есть ли способ сделать это без сна? – mozcelikors

+0

Другое дело, что у меня есть первичный выход, но с Fatal IO error 11. Должен ли я ожидать эту ошибку? – mozcelikors

+0

Тем не менее, дает мне представление о инструкциях, спасибо. – mozcelikors

5

Используйте subprocess.Popen для запуска perf. Затем используйте pipe.communicate() для отправки ввода и получения вывода процесса.

После того, как вы это сделали, позвоните по телефону pipe.terminate(), чтобы завершить процесс.

Например:

pipe = subprocess.Popen(["perf","stat","-p",str(GetMyProcessID())], stdout=PIPE) 

pipe.terminate() 
stdout, stderr = pipe.communicate() 
print stdout 
+0

Здравствуйте, я хочу отправить pipe = subprocess.Popen (["perf", "stat", " -p ", str (GetMyProcessID())]) и вывод перед завершением. Мне не нужно посылать какую-либо команду ввода, кроме Popen. Теперь программа застревает на линии stdout, stderr = pipe.communicate (None). Что я должен сделать?Спасибо – mozcelikors

+0

@mozcelikors Я должен был использовать 'stdout = PIPE' в качестве параметра для подпрограмм.Popen. Я обновляю ответ. –

+0

, но все же pipe.communicate блокирует. Мне нужно что-то неблокирующее. Или просто я хочу получить выход, когда труба завершена. Поэтому он должен запускаться, когда я его вызываю, но результат должен возвращаться, когда я его завершаю. – mozcelikors

Смежные вопросы