Как убить процесс с помощью многопроцессорного модуля? - PullRequest
0 голосов
/ 28 февраля 2019

У меня есть процесс, который по сути является просто бесконечным циклом, и у меня есть второй процесс, который является таймером.Как я могу завершить процесс цикла после завершения таймера?

def action():
  x = 0
  while True:
      if x < 1000000:
          x = x + 1
      else:
          x = 0

def timer(time):
  time.sleep(time)
  exit()    

loop_process = multiprocessing.Process(target=action)
loop_process.start()
timer_process = multiprocessing.Process(target=timer, args=(time,))
timer_process.start()

Я хочу, чтобы скрипт python завершился после завершения таймера.

Ответы [ 3 ]

0 голосов
/ 28 февраля 2019

Вы можете сделать это, используя состояние совместного использования между процессами и создав значение флага, к которому могут обращаться все параллельные процессы (хотя это может быть несколько неэффективно).

Вот что я предлагаю:

import multiprocessing as mp
import time

def action(run_flag):
    x = 0
    while run_flag.value:
        if x < 1000000:
            x = x + 1
        else:
            x = 0

    print('action() terminating')


def timer(run_flag, secs):
    time.sleep(secs)
    run_flag.value = False


if __name__ == '__main__':

    run_flag = mp.Value('I', True)

    loop_process = mp.Process(target=action, args=(run_flag,))
    loop_process.start()

    timer_process = mp.Process(target=timer, args=(run_flag, 2.0))
    timer_process.start()

    loop_process.join()
    timer_process.join()

    print('done')
0 голосов
/ 28 февраля 2019

Я думаю, вам не нужно делать второй процесс только для таймера.

Graceful Timeout

В случае, если вам нужно очистить перед выходом в процессе action, выможет использовать Timer -поток и позволить циклу while проверить, жив ли он еще.Это позволяет вашему рабочему процессу корректно завершиться, но вам придется платить с пониженной производительностью, потому что повторный вызов метода занимает некоторое время.Не должно быть проблем, если это не жесткий цикл.

from multiprocessing import Process
from datetime import datetime
from threading import Timer


def action(runtime, x=0):
    timer = Timer(runtime, lambda: None)  # just returns None on timeout
    timer.start()
    while timer.is_alive():
        if x < 1_000_000_000:
            x += 1
        else:
            x = 0

if __name__ == '__main__':

    RUNTIME = 1

    p = Process(target=action, args=(RUNTIME,))
    p.start()
    print(f'{datetime.now()} {p.name} started')
    p.join()
    print(f'{datetime.now()} {p.name} ended')

Пример вывода:

2019-02-28 19:18:54.731207 Process-1 started
2019-02-28 19:18:55.738308 Process-1 ended

Завершение по таймауту

Если вам не нужно закрывать clean (вы не используете общие очереди, не работаете с БД и т. Д.), Вы можете разрешить родительскому процессу terminate() рабочий процесс послеВаше указанное время.

terminate ()

Завершить процесс.В Unix это делается с помощью сигнала SIGTERM;в Windows используется TerminateProcess ().Обратите внимание, что обработчики выхода и предложения finally и т. Д. Не будут выполняться.

Обратите внимание, что процессы-потомки процесса не будут завершены - они просто станут осиротевшими.

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

Если вам не нужно ничего делать с родителем, вы можете просто .join(timeout) рабочий процесс и .terminate() впоследствии.

from multiprocessing import Process
from datetime import datetime

def action(x=0):
    while True:
        if x < 1_000_000_000:
            x += 1
        else:
            x = 0

if __name__ == '__main__':

    RUNTIME = 1

    p = Process(target=action)
    p.start()
    print(f'{datetime.now()} {p.name} started')
    p.join(RUNTIME)
    p.terminate()
    print(f'{datetime.now()} {p.name} terminated')

Пример вывода:

2019-02-28 19:22:43.705596 Process-1 started
2019-02-28 19:22:44.709255 Process-1 terminated

Если вы хотите использовать terminate(), но хотите, чтобы ваш родитель был разблокирован, вы также можете использовать Timer -thread внутри родительского элемента дляthat.

from multiprocessing import Process
from datetime import datetime
from threading import Timer

def action(x=0):
    while True:
        if x < 1_000_000_000:
            x += 1
        else:
            x = 0


def timeout(process, timeout):
    timer = Timer(timeout, process.terminate)
    timer.start()


if __name__ == '__main__':

    RUNTIME = 1

    p = Process(target=action)
    p.start()
    print(f'{datetime.now()} {p.name} started')
    timeout(p, RUNTIME)
    p.join()
    print(f'{datetime.now()} {p.name} terminated')

Пример вывода:

2019-02-28 19:23:45.776951 Process-1 started
2019-02-28 19:23:46.778840 Process-1 terminated
0 голосов
/ 28 февраля 2019

Простой оператор возврата после else в action() будет работать отлично.Кроме того, у вас была ошибка в вашей timer функции.У вашего аргумента было то же имя, что и у встроенной библиотеки.

def action():
   x = 0
   while True:
      if x < 1000000:
         x = x + 1
      else:
         x = 0
         return # To exit else it will always revolve in infinite loop

def timer(times):
   time.sleep(times)
   exit()    

loop_process = multiprocessing.Process(target=action)
loop_process.start()
timer_process = multiprocessing.Process(target=timer(10))
timer_process.start()

Надеюсь, это ответит на ваш вопрос !!!

...