Как убить процесс, который создается popen и использует connect ()?

1

У меня есть программа, P1, которую мне нужно запустить около 24 * 20000 раз с разными входами. Проблема в том, что P1 зависает, и я должен заставить его полностью вручную (kill). Моим первым решением было написать скрипт python для вызова P1 и передачи правильного ввода и получения вывода с использованием popen и communicate. Но из-за характера сообщения, которое ждет выхода, я не могу убить процесс, пока он ждет ответа. Я нахожусь в Windows.

Я попытался использовать функцию multiprocess, но он запускает только P1 и не смог отправить ему вход. Я с подозрением отношусь к тому, чтобы не использовать каналы в popen и немного потрудился, но, я думаю, я не могу получить вывод из P1.

Есть идеи?

# This code run XLE and pass the intended input to it automatically
 def startExe(programPath, programArgStr):
 p = subprocess.Popen(programPath,stdout=subprocess.PIPE,stdin=subprocess.PIPE) p.stdin.write(programArgStr)
 p.communicate()[0]
# Need to kill the process if it takes longer than it should here

def main(folder): 
.. 
#loop
programArgStr = "create-parser"+path1+";cd "+ path2+"/s"+ command(counter) +";exit"

startExe(path, programArgStr)
..

Как вы можете видеть, может ли P1 успешно завершить заданное задание, он может выйти из себя, используя команды выхода, переданные ему!

Теги:
kill
subprocess
popen
terminate

4 ответа

0
Лучший ответ

Я решил свою проблему, отредактировав текущий код и поместив код убийцы в отдельный файл. для этого я добавляю строку для записи PID вновь созданного процесса в файл.

    #//Should come before p.commiunicate
    WriteStatus(str(p.pid) + "***" + str(gmtime().tm_hour) + "***" + str(gmtime().tm_min))        
    p.communicate()[0]

Монитор процесса выполняется отдельно и проверяет каждые 2 минуты, чтобы проверить, все ли процессы, перечисленные в файле, активны. Если да, убейте их и удалите их ID.

 def KillProcess(pid):

    subprocess.Popen("TASKKILL /PID "+ str(pid) + " /F /T" , shell=True)
    subprocess.Popen("TASKKILL /im WerFault.exe /F /T" , shell=True)
    print "kill"

    def ReadStatus(filePath):
    print "Checking" + filePath
    try:
            status = open(mainPath+filePath, 'r').readline()
    except:
            print "file removed" + filePath
            return 0
    if len(status) >0:
            info = status.split("***")                
            time = [gmtime().tm_hour, gmtime().tm_min]
            print time

            # Time deifferences
            difHour = time[0]- int(info[1])
            if difHour == 0: # in the same hour
                    difMin =  time[1]- int(info[2])
            else:
                    difMin = 60 - int(info[2]) + time[1]
            if difMin > 2:
                    try:
                            open(mainPath+filePath, 'w').write("")
                            KillProcess(info[0])
                    except:
                            pass
    return 1

  def monitor():
    # Read all the files
    listFiles = os.listdir(mainPath)
    while len(listFiles)>0:
            #GO and check the contents
            for file in listFiles:
                    #Open the file and Calculate if the process should be killed or not
                    pid = ReadStatus(file)
                    #Update listFiles due to remove of file after finishing the process '
                    # of each folder is done
                    listFiles = os.listdir(mainPath)
            for i in range(0,4):
                    time.sleep(30) #waits 30 sec
                    subprocess.Popen("TASKKILL /im WerFault.exe /F /T" , shell=True)
    #to indicate the job is done
    return 1
2

Когда вы вызываете popen, вы можете указать либо дескриптор канала или файла, чтобы принять stdout из процесса:

Popen (args, bufsize = 0, executable = None, stdin = None, stdout = None, stderr = None, preexec_fn = None, close_fds = False, shell = False, cwd = None, env = None, universal_newlines = False, startupinfo = None, creationflags = 0)

Затем вы можете отслеживать файл/трубу, которую вы передаете, в popen, и если ничего не написано, убейте процесс.

Дополнительная информация о popen args содержится в документах python.

Вместо того, чтобы использовать p.communicate, попробуйте просто p.communicate строки вывода:

while True:
    line = p.stdout.readline()
    if not line:
        break
    print ">>> " + line.rstrip()
2

Если вам не требуется использовать Python, вы можете использовать Cygwin Bash вместе с командой timeout(1) для запуска команды с таймаутом. Тем не менее, поскольку реализация Cykwin fork() не очень быстро, и вы создаете огромное количество процессов, у вас, вероятно, будет огромная накладная работа только за создание процессов (я не знаю, является ли родная версия Windows Python лучше в этом отношении).

В качестве альтернативы, если у вас есть исходный код для P1, почему бы вам просто не изменить его, чтобы он мог выполнять несколько итераций того, что он делает в одном вызове? Таким образом, вам не нужно заниматься созданием и уничтожением 480 000 процессов, что будет иметь огромное значение, если количество работы, которую выполняет каждый вызов, невелико.

  • 0
    В действительности у меня нет доступа к исходному коду P1. Я могу просто выполнить это. Я не получил точно, что я могу сделать с CygWin. Не могли бы вы объяснить мне больше? Ниже приведены некоторые фрагменты моего кода. <code> # Этот код запускает XLE и автоматически передает ему входные данные def startExe (programPath, programArgStr): p = subprocess.Popen (programPath, stdout = subprocess.PIPE, stdin = subprocess.PIPE) p.stdin.write ( programArgStr) p.communicate () [0] def main (folder): .. programArgStr = "create-parser" + path1 + "; cd" + path2 + "/ s" + command (counter) + ". txt; +"; Выход"
  • 0
    Я пытался отредактировать свой вопрос, не могли бы вы помочь мне с этим снова?
0

Как насчет этого подхода?

from threading import Thread
def main(input):
    #your actual program, modified to take input as argument
queue = ['Your inputs stored here. Even better to make it to be a generator']
class Runner(Thread):
    def __init__(self):
        Thread.__init__(self)
    def run(self):
        while len(queue)>0:
            input = queue.pop()
            main(input)
        return True
#Use 24 threads
for thread in xrange(24):
    Runner().start()
#You may also join threads at the end.

Разумеется, этот подход приведет к некоторым уязвимостям, таким как "два потока по очереди списка очередей одновременно", но я никогда не сталкивался с ним в реальной жизни.

  • 0
    Извините, у меня нет доступа к моей программе ввода :(

Ещё вопросы

Сообщество Overcoder
Наверх
Меню