1. ホーム
  2. python

[解決済み] Python Process Poolは非貴重?

2022-08-03 04:18:52

質問

PythonのPoolで非発音型のものを作ることは可能でしょうか?私は、プールが内部に別のプールを持つ関数を呼び出すことができるようにしたいです。

deamonプロセスはプロセスを作成することができないので、私はこれが欲しいです。具体的には、それはエラーを引き起こします。

AssertionError: daemonic processes are not allowed to have children

例えば、次のようなシナリオを考えてみましょう。 function_a を実行するプールがある場合を考えてみましょう。 function_b を実行するプールを持つ function_c . この関数チェーンは失敗します。 function_b はデーモンプロセスで実行されており、デーモンプロセスはプロセスを作成することができないためです。

どのように解決するのですか?

この multiprocessing.pool.Pool クラスはワーカープロセスをその __init__ メソッドで作成し、デーモン化し、起動します。 daemon 属性を False を追加することができます (その後、それはもう許されません)。しかし、独自のサブクラスを作成することで multiprocesing.pool.Pool ( multiprocessing.Pool は単なるラッパー関数です)に置き換え、独自の multiprocessing.Process サブクラスで、ワーカープロセスに使用するために常に非デモニックです。

以下は、この方法の完全な例です。重要な部分は、2つのクラス NoDaemonProcessMyPool を上部に配置し pool.close()pool.join() を、あなたの MyPool のインスタンスを最後に追加します。

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

import multiprocessing
# We must import this explicitly, it is not imported by the top-level
# multiprocessing module.
import multiprocessing.pool
import time

from random import randint


class NoDaemonProcess(multiprocessing.Process):
    # make 'daemon' attribute always return False
    def _get_daemon(self):
        return False
    def _set_daemon(self, value):
        pass
    daemon = property(_get_daemon, _set_daemon)

# We sub-class multiprocessing.pool.Pool instead of multiprocessing.Pool
# because the latter is only a wrapper function, not a proper class.
class MyPool(multiprocessing.pool.Pool):
    Process = NoDaemonProcess

def sleepawhile(t):
    print("Sleeping %i seconds..." % t)
    time.sleep(t)
    return t

def work(num_procs):
    print("Creating %i (daemon) workers and jobs in child." % num_procs)
    pool = multiprocessing.Pool(num_procs)

    result = pool.map(sleepawhile,
        [randint(1, 5) for x in range(num_procs)])

    # The following is not really needed, since the (daemon) workers of the
    # child's pool are killed when the child is terminated, but it's good
    # practice to cleanup after ourselves anyway.
    pool.close()
    pool.join()
    return result

def test():
    print("Creating 5 (non-daemon) workers and jobs in main process.")
    pool = MyPool(5)

    result = pool.map(work, [randint(1, 5) for x in range(5)])

    pool.close()
    pool.join()
    print(result)

if __name__ == '__main__':
    test()