web-dev-qa-db-ja.com

multiprocessingは「too many open files」を返しますが、「with ... as」を使用すると修正されます。どうして?

私は この回答 を使用して、LinuxボックスでPythonのマルチプロセッシングで並列コマンドを実行しました。

私のコードは次のようなことをしました:

import multiprocessing
import logging

def cycle(offset):
    # Do stuff

def run():
    for nprocess in process_per_cycle:
        logger.info("Start cycle with %d processes", nprocess)
        offsets = list(range(nprocess))
        pool = multiprocessing.Pool(nprocess)
        pool.map(cycle, offsets)

しかし、私はこのエラーを受け取っていました:OSError: [Errno 24] Too many open files
そのため、コードが開いているファイル記述子が多すぎました。つまり、開始したプロセスが多すぎて終了していませんでした。

最後の2行を次の行に置き換えて修正しました。

    with multiprocessing.Pool(nprocess) as pool:
        pool.map(cycle, offsets)

しかし、これらの行がそれを修正した理由は正確にはわかりません。

そのwithの下で何が起こっていますか?

12
nephewtom

ループ内に新しいプロセスを作成し、それらの処理が完了したら閉じるのを忘れています。その結果、開いているプロセスが多すぎるという点があります。これは悪い考えです。

pool.terminateを自動的に呼び出すコンテキストマネージャーを使用するか、自分でpool.terminateを手動で呼び出すことにより、これを修正できます。または、ループの外側にプールを作成してonceだけにしてから、内部のプロセスにタスクを送信してみませんか?

pool = multiprocessing.Pool(nprocess) # initialise your pool
for nprocess in process_per_cycle:
    ...       
    pool.map(cycle, offsets) # delegate work inside your loop

pool.close() # shut down the pool

詳細については、 multiprocessing.Pool のドキュメントをご覧ください。

11
cs95

コンテキストマネージャーです。 withを使用すると、ファイルを適切に開いたり閉じたりできます。これを詳細に理解するには、この記事をお勧めします https://jeffknupp.com/blog/2016/03/07/python-with-context-managers/

1
pritesh