AttributeError: 'Pool' object has no attribute '__exit__'

user1251007 picture user1251007 · Nov 21, 2014 · Viewed 11.9k times · Source

I'm doing some multiprocessing python scripts using multiprocessing.Pool. These scripts look like the following:

from multiprocessing import Pool

def f(x):
    return x*x

if __name__ == '__main__':
    with Pool(processes=4) as pool:         # start 4 worker processes
        print(pool.map(f, range(10)))       # prints "[0, 1, 4,..., 81]"

When running this with Python 3.4, everything is fine. However, when using Python 2.6 or 3.1 I get this error:

AttributeError: 'Pool' object has no attribute '__exit__'

Using Python 2.7 or 3.2, the error is essentially the same:

AttributeError: __exit__

Why does this happen and how can I circumvent this?

Answer

user1251007 picture user1251007 · Nov 21, 2014

The documentation says that multiprocessing.pool supports the context management protocol (with statements) in Python version 3.3 and above.

New in version 3.3: Pool objects now support the context management protocol – see Context Manager Types. __enter__() returns the pool object, and __exit__() calls terminate().

So you either need a newer version of Python, or use one of the two following possibilities changing your code (tested with Python versions 2.6, 2.7, 3.1, 3.2):

  1. rewrite your code like this to eliminate the with statement:

    from multiprocessing import Pool
    
    def f(x):
        return x*x
    
    if __name__ == '__main__':
        pool = Pool(processes=4)            # start 4 worker processes
        print(pool.map(f, range(10)))       # prints "[0, 1, 4,..., 81]"
        pool.terminate()
    
  2. as pointed out in the comments, use contextlib.closing():

    from multiprocessing import Pool
    import contextlib
    
    def f(x):
        return x*x
    
    if __name__ == '__main__':
        with contextlib.closing(Pool(processes=4)) as pool:
            print(pool.map(f, range(10)))