2014-08-13

Python: how to stop process correctly

Одной из задач, с которой встречаются разработчики многопоточных/многопроцессных приложений, является их корректная остановка. Особенно это касается таких потоков/процессов, в которых осуществляется бесконечная блокирующая операция, типа цикла "while True" или чтения из некоего генератора.

while True:
    # do something
С потоками проще, потому что им можно передать ссылку на объект, который можно проверять при каждой итерации и останавливать при соблюдении условий.

import time
from threading import Thread

def in_thread(con):
    while con[0]:
        # ... doing something
        pass

con = [True]
t = Thread(target=in_thread, args=(con,))
t.start()

time.sleep(3)
# Stop the thread
con[0] = False
t.join()
С процессами несколько иначе, они более изолированные, и нужно использовать объекты синхронизации. Очень удобный способ мне подсказал коллега, с использованием Lock.

import time
from threading import Thread
from multiprocessing import Process, Lock

def in_process(lock):

    def in_thread(con):
        while con[0]:
            pass
            # ... doing something

    con = [True]
    t = Thread(target=in_thread, args=(con,))
    t.daemon = True
    t.start()

    # Lock acquired in parent process, child process waits, but thread already ran!
    lock.acquire()

    # Polite way
    con[0] = False
    t.join()

    # Way for impatient
    # import os
    # os._exit(0)


lock = Lock()
lock.acquire()
Process(target=in_process, args=(lock,)).start()

time.sleep(3)
# ... process in action ...

# Release lock, child process going to be finished
lock.release()