这是 AFAIK 未记录的,但multiprocessing
有一个Finalizer
类,“它支持使用弱引用进行对象终结”。您可以使用它在您的initializer
.
不过,在这种情况下,我看不到multiprocessing.Value
有用的同步选择。多个工作人员可以同时退出,表明哪些文件整数是空闲的,这比(锁定的)计数器所能提供的要多。
我建议使用多个 bare multiprocessing.Lock
s,每个文件一个,而不是:
from multiprocessing import Pool, Lock, current_process
from multiprocessing.util import Finalize
def f(n):
global fileno
for _ in range(int(n)): # xrange for Python 2
pass
return fileno
def init_fileno(file_locks):
for i, lock in enumerate(file_locks):
if lock.acquire(False): # non-blocking attempt
globals()['fileno'] = i
print("{} using fileno: {}".format(current_process().name, i))
Finalize(lock, lock.release, exitpriority=15)
break
if __name__ == '__main__':
n_proc = 3
file_locks = [Lock() for _ in range(n_proc)]
pool = Pool(
n_proc, initializer=init_fileno, initargs=(file_locks,),
maxtasksperchild=2
)
print(pool.map(func=f, iterable=[50e6] * 18))
pool.close()
pool.join()
# all locks should be available if all finalizers did run
assert all(lock.acquire(False) for lock in file_locks)
输出:
ForkPoolWorker-1 using fileno: 0
ForkPoolWorker-2 using fileno: 1
ForkPoolWorker-3 using fileno: 2
ForkPoolWorker-4 using fileno: 0
ForkPoolWorker-5 using fileno: 1
ForkPoolWorker-6 using fileno: 2
[0, 0, 1, 1, 2, 2, 0, 0, 1, 1, 2, 2, 0, 0, 1, 1, 2, 2]
Process finished with exit code 0
请注意,在 Python 3 中,您不能可靠地使用 Pool 的上下文管理器,而不是使用上面显示的旧方法。Pool 的上下文管理器(不幸的是)调用,这可能会在终结器有机会运行之前terminate()
杀死工作进程。