2015-12-29 2 views
5

У меня есть некоторые подпроцессы (с использованием многопроцессорности), и когда они останавливаются, каждый из них нуждается в некоторой конечной работе. Что-то вроде следующего, которое не работает, хотя ...Как зарегистрировать функцию «atexit» в подпроцессе многопроцессорности python?

import multiprocessing 
import atexit 

def final(): 
    print "final work" 

def worker(): 
    print 'Doing some work' 
    atexit.register(final) 

if __name__ == '__main__': 
    p = multiprocessing.Process(target=worker) 
    p.start() 
    p.join() 

Так как я могу это сделать?

+0

Проверьте http://stackoverflow.com/questions/1231599/python-multiprocessing-exit-elegantly-how, что похоже на то, что вы пытаетесь выполнить. –

ответ

1

Процессы, запущенные с помощью многопроцессорной обработки, не выходят из строя, а функции atexit не вызываются. Вы должны запустить очистки материала вручную с помощью Try /, наконец, блок, например:

def worker(): 
    try: 
     print('Doing some work') 
    finally: 
     final() 

Или, если вы действительно хотите использовать atexit (см ниже недостатков):

def worker(): 
    try: 
     print('Doing some work') 
    finally: 
     atexit._run_exitfuncs() 

Почему не выполняются подпроцессы нормально?

Технически, потому что they quit via os._exit(), пропуская любую работу по очистке (в том числе atexit функции, __del__() и слабинные финализаторы).

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

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

+0

Это было абсурдное решение. Функции atexit не ожидают, что их вызывают из «main». Они ожидают, что их вызовут в процессе регистрации. поэтому atexit просто нужно хранить pid регистрации, чтобы узнать, могут ли они быть вызваны. Любые модули, которые используют atexit, теперь оказываются бесполезными в многопроцессорном задании ... заставляя меня использовать Popen вместо этого и рассолить их собственное состояние. Я на самом деле разветвлял многопроцессорность, чтобы снова включить правильные очистки. –

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