

# やりたいこと

以下のコードのように、Pythonの`multiprocessing.Pool`を使って並列に処理したいです。

[code]

    import multiprocessing
    
    def foo(i):
        if i%2==0:
            raise RuntimeError("偶数")
        return i
    
    with multiprocessing.Pool(4) as p:
        result = p.map(foo, [1, 3, 5])
        print(result)
        # => [1, 3, 5]
    
[/code]

# 質問

以下のように`[1,2,3]`をmap関数に渡すと、`i=2`のときにRuntimeErrorがスローされます。

[code]

    with multiprocessing.Pool(4) as p:
        result = p.map(foo, [1,2,3])
    
[/code]

[code]

    RemoteTraceback: 
    """
    Traceback (most recent call last):
      File "/home/vagrant/.pyenv/versions/3.9.7/lib/python3.9/multiprocessing/pool.py", line 125, in worker
        result = (True, func(*args, **kwds))
      File "/home/vagrant/.pyenv/versions/3.9.7/lib/python3.9/multiprocessing/pool.py", line 48, in mapstar
        return list(map(*args))
      File "<ipython-input-102-bbf59efb0d82>", line 3, in foo
        raise RuntimeError("偶数")
    RuntimeError: 偶数
    """
    
[/code]

`i=2`のときの例外をキャッチした上で、`i=1`, `i=3`のときの結果も取得したいです。どのようなコードを書けばよいでしょうか？

以下のコードのように、`foo`関数の中でtry/exceptすれば、`i=1`, `i=3`のときの結果を取得できます。  
しかし、本来try/exceptはfoo関数の呼び出し元で行うべきなので、できればこの方法は採用したくありません。

[code]

    def foo(i):
        try:
            if i%2==0:
                raise RuntimeError("custom")
            return i
        except Exception
            return None
    
[/code]


CC BY-SA 4.0
2022-02-23T06:12:22.247
86528
2022-02-23T11:25:36.113
2022-02-23T09:03:44.183
2238
19524
question
python
マルチプロセスで処理する際、例外をキャッチした上で処理を継続したいです


[ここ](https://stackoverflow.com/a/44819075/9105334)にあるように、[`imap`メソッド](https://docs.python.org/ja/3/library/multiprocessing.html#multiprocessing.pool.Pool.imap)を使ってイテレーターを取得し、例外を処理しながらイテレーターを進めていくのはいかがでしょうか。

[code]

    import multiprocessing
    
    def foo(i):
        if i % 2 == 0:
            raise RuntimeError(f"偶数: {i}")
        return i
    
    if __name__ == '__main__':
        with multiprocessing.Pool(4) as p:
            result_iterator = p.imap(foo, [1, 2, 3])
            while True:
                try:
                    result = next(result_iterator)
                    print(result)
                except StopIteration:
                    break
                except Exception as e:
                    print(e)
    
    
[/code]


CC BY-SA 4.0
2022-02-23T11:25:36.113
86537
2022-02-23T11:25:36.113
36010
86528
answer