Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ProcessPoolExecutor documentation reports wrong exception being raised #78967

Closed
kahara mannequin opened this issue Sep 24, 2018 · 4 comments
Closed

ProcessPoolExecutor documentation reports wrong exception being raised #78967

kahara mannequin opened this issue Sep 24, 2018 · 4 comments
Labels
3.7 (EOL) end of life 3.8 only security fixes docs Documentation in the Doc dir

Comments

@kahara
Copy link
Mannequin

kahara mannequin commented Sep 24, 2018

BPO 34786
Nosy @tirkarthi, @kahara
PRs
  • bpo-34786: Fix wrong exception reference: BrokenThreadPool -> BrokenProcessPool  #9533
  • [3.7] bpo-34786: Fix wrong exception reference: BrokenThreadPool -> BrokenProcessPool (GH-9533) #9554
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = None
    closed_at = <Date 2018-09-25.03:38:07.732>
    created_at = <Date 2018-09-24.12:32:16.067>
    labels = ['3.7', '3.8', 'docs']
    title = 'ProcessPoolExecutor documentation reports wrong exception being raised'
    updated_at = <Date 2018-09-25.03:38:07.731>
    user = 'https://github.com/kahara'

    bugs.python.org fields:

    activity = <Date 2018-09-25.03:38:07.731>
    actor = 'xiang.zhang'
    assignee = 'docs@python'
    closed = True
    closed_date = <Date 2018-09-25.03:38:07.732>
    closer = 'xiang.zhang'
    components = ['Documentation']
    creation = <Date 2018-09-24.12:32:16.067>
    creator = 'kahara'
    dependencies = []
    files = []
    hgrepos = []
    issue_num = 34786
    keywords = ['patch']
    message_count = 4.0
    messages = ['326226', '326231', '326234', '326235']
    nosy_count = 3.0
    nosy_names = ['docs@python', 'xtreak', 'kahara']
    pr_nums = ['9533', '9554']
    priority = 'normal'
    resolution = 'fixed'
    stage = 'resolved'
    status = 'closed'
    superseder = None
    type = None
    url = 'https://bugs.python.org/issue34786'
    versions = ['Python 3.7', 'Python 3.8']

    @kahara
    Copy link
    Mannequin Author

    kahara mannequin commented Sep 24, 2018

    https://docs.python.org/3.8/library/concurrent.futures.html

    "initializer is an optional callable that is called at the start of each worker process; initargs is a tuple of arguments passed to the initializer. Should initializer raise an exception, all currently pending jobs will raise a BrokenThreadPool, as well any attempt to submit more jobs to the pool."

    This should be BrokenProcessPool?

    @kahara kahara mannequin added 3.7 (EOL) end of life 3.8 only security fixes labels Sep 24, 2018
    @kahara kahara mannequin assigned docspython Sep 24, 2018
    @kahara kahara mannequin added the docs Documentation in the Doc dir label Sep 24, 2018
    @tirkarthi
    Copy link
    Member

    I think it raises BrokenThreadPool . A sample program that I tried as below raising an exception in the initializer. Maybe I am wrong here. Can you please attach a script that triggers BrokenProcessPool?

    # bpo-34786.py

    import concurrent.futures
    import time
    
    def bar(i):
        raise Exception(i) # Raise exception from the initializer
    
    def foo(i):
        time.sleep(i)
        return "1"

    with concurrent.futures.ThreadPoolExecutor(max_workers=5,
    initializer=bar, initargs=(1,)) as executor:
    future_to_url = {executor.submit(foo, i, 60): i for i in range(10)}
    for future in concurrent.futures.as_completed(future_to_url):
    try:
    data = future.result()
    except Exception as exc:
    print('generated an exception: %s' % (exc))
    else:
    print('%d bytes' % (len(data)))

    # Run the program

    ./python.exe ../backups/bpo34786.py
    Exception in initializer:
    Traceback (most recent call last):
      File "/Users/karthikeyansingaravelan/stuff/python/cpython/Lib/concurrent/futures/thread.py", line 69, in _worker
        initializer(*initargs)
      File "../backups/bpo34786.py", line 5, in bar
        raise Exception(i)
    Exception: 1
    Exception in initializer:
    Traceback (most recent call last):
      File "/Users/karthikeyansingaravelan/stuff/python/cpython/Lib/concurrent/futures/thread.py", line 69, in _worker
        initializer(*initargs)
      File "../backups/bpo34786.py", line 5, in bar
        raise Exception(i)
    Exception: 1
    Traceback (most recent call last):
      File "../backups/bpo34786.py", line 13, in <module>
        future_to_url = {executor.submit(foo, i, 60): i for i in range(10)}
      File "../backups/bpo34786.py", line 13, in <dictcomp>
        future_to_url = {executor.submit(foo, i, 60): i for i in range(10)}
      File "/Users/karthikeyansingaravelan/stuff/python/cpython/Lib/concurrent/futures/thread.py", line 148, in submit
        raise BrokenThreadPool(self._broken)
    concurrent.futures.thread.BrokenThreadPool: A thread initializer failed, the thread pool is not usable anymore

    Thanks

    @kahara
    Copy link
    Mannequin Author

    kahara mannequin commented Sep 24, 2018

    Perhaps I wasn't clear that this considered ProcessPoolExecutor documentation, not ThreadPoolExecutor. Taking the example from documentation and adding an initializer like this:

    import concurrent.futures
    import math
    
    PRIMES = [
        112272535095293,
        112582705942171,
        112272535095293,
        115280095190773,
        115797848077099,
        1099726899285419]
    
    def is_prime(n):
        if n % 2 == 0:
            return False
    
        sqrt_n = int(math.floor(math.sqrt(n)))
        for i in range(3, sqrt_n + 1, 2):
            if n % i == 0:
                return False
        return True
    
    def init():
        raise Exception()
    
    def main():
        with concurrent.futures.ProcessPoolExecutor(initializer=init) as executor:
            for number, prime in zip(PRIMES, executor.map(is_prime, PRIMES)):
                print('%d is prime: %s' % (number, prime))
    
    if __name__ == '__main__':
        main()

    ...yields the following:

    Exception in initializer:
    Traceback (most recent call last):
      File "/Users/developer/cpython/Lib/concurrent/futures/process.py", line 219, in _process_worker
        initializer(*initargs)
      File "/tmp/bpo34786.py", line 25, in init
        raise Exception()
    Exception
    Exception in initializer:
    Traceback (most recent call last):
      File "/Users/developer/cpython/Lib/concurrent/futures/process.py", line 219, in _process_worker
        initializer(*initargs)
      File "/tmp/bpo34786.py", line 25, in init
        raise Exception()
    Exception
    Exception in initializer:
    Traceback (most recent call last):
      File "/Users/developer/cpython/Lib/concurrent/futures/process.py", line 219, in _process_worker
        initializer(*initargs)
      File "/tmp/bpo34786.py", line 25, in init
        raise Exception()
    Exception
    Exception in initializer:
    Traceback (most recent call last):
      File "/Users/developer/cpython/Lib/concurrent/futures/process.py", line 219, in _process_worker
        initializer(*initargs)
      File "/tmp/bpo34786.py", line 25, in init
        raise Exception()
    Exception
    Traceback (most recent call last):
      File "/tmp/bpo34786.py", line 33, in <module>
        main()
      File "/tmp/bpo34786.py", line 29, in main
        for number, prime in zip(PRIMES, executor.map(is_prime, PRIMES)):
      File "/Users/developer/cpython/Lib/concurrent/futures/process.py", line 476, in _chain_from_iterable_of_lists
        for element in iterable:
      File "/Users/developer/cpython/Lib/concurrent/futures/_base.py", line 594, in result_iterator
        yield fs.pop().result()
      File "/Users/developer/cpython/Lib/concurrent/futures/_base.py", line 436, in result
        return self.__get_result()
      File "/Users/developer/cpython/Lib/concurrent/futures/_base.py", line 388, in __get_result
        raise self._exception
    concurrent.futures.process.BrokenProcessPool: A process in the process pool was terminated abruptly while the future was running or pending.

    @tirkarthi
    Copy link
    Member

    Got it. Sorry about that I copy pasted the quoted string and assumed ThreadPoolExecutor overlooking the PR. The change is reasonable to me.

    Thanks

    @ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    3.7 (EOL) end of life 3.8 only security fixes docs Documentation in the Doc dir
    Projects
    None yet
    Development

    No branches or pull requests

    2 participants