2016-11-03 3 views
2

Что происходит с потоками daemon при выходе основного потока? Как они закрываются? Есть ли способ обеспечить выполнение кода очистки?Как уничтожаются потоки демона в python (2.7)

Вот эскиз ситуации у меня есть:

import os 
import subprocess 
import threading 
import glob 
import datetime 

def do_big_job(result='result.txt'): 
    tmpfile = result+'.tmp' 
    err = subprocess.call(['my_time_consuming_script', '-o', tmpfile]) 
    if err == 0: 
     os.rename(tmpfile, result) 
    else: 
     os.remove(tmpfile) # process failed, clean up temp file 



def main(): 
    not_done = True 
    update = 0 
    while not_done: 

     # we can see if new data are available, 
     # and start a process to get/prep it 
     if new_data_available(): 
      args = ('result{0:05}.txt'.format(update),) 
      th = threading.Thread(target=do_big_job, args=args) 
      update = update + 1 
      th.daemon = True 
      th.start() 

     # but we don't need/want to wait for that process 
     # to complete before continuing to iterate 

     currently_available = glob.glob('result*.txt') 
     # <snip> 
     # rest of loop just uses what is available, 
     # we don't want/need to block for updated data 
     # to meet other responsiveness requirements 

Я хотел бы, чтобы убедиться, что я не оставляю никаких временных файлов (или зомби-процессов), лежащих вокруг, если основной поток умирает в то время как один (или более) потоков do_big_job все еще работает, но я также не могу просто установить daemon=False, так как я не могу дождаться их завершения, когда основные выходы.

ответ

1

Когда основной поток выходит из всех потоков демона, выйдите тоже. Поэтому, если ваш main() выйдет из всех потоков демонов, выйдет тоже.

Тем не менее, идя во вторую часть вашего вопроса, в соответствии с официальным потоком python docs для операций ввода-вывода это может случиться не изящно.

Нитки демона внезапно останавливаются при выключении. Их ресурсы (такие как открытые файлы, транзакции базы данных и т. Д.) Могут быть недоступны. Если вы хотите, чтобы ваши потоки прекратились изящно, сделайте их не-демоническими и используйте подходящий механизм сигнализации, такой как событие.

Итак, если вы хотите проверить, есть ли какие-либо зомби-нитки, вы можете вызвать функцию isAlive(). Теперь о том, как обеспечить, чтобы код очистки выполнялся после того, как основной поток замирает; Я думаю, это зависит от того, что вы подразумеваете под умирает.

Если вы имеете в виду нормальный выход скрипта (например, исключение KeyboardInterrupt, вызывается sys.exit()), то действительно стоит взглянуть на модуль atexit, который регистрирует функции, которые будут выполняться после завершения процесса.

Если «умирающий» означает, что main() убит сигналом или возникает внутренняя ошибка Python, или вызывается os._exit(), то модуль atexit не будет работать. В этом случае возможным решением, которое приходит мне на ум, было бы создание еще одного сторожевого процесса, который постоянно контролирует ваш основной() и будет запускать код очистки, когда это необходимо.

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