| 650 | |
| 651 | |
| 652 | class ProcessPoolExecutor(_base.Executor): |
| 653 | def __init__(self, max_workers=None, mp_context=None, |
| 654 | initializer=None, initargs=(), *, max_tasks_per_child=None): |
| 655 | """Initializes a new ProcessPoolExecutor instance. |
| 656 | |
| 657 | Args: |
| 658 | max_workers: The maximum number of processes that can be used to |
| 659 | execute the given calls. If None or not given then as many |
| 660 | worker processes will be created as the machine has processors. |
| 661 | mp_context: A multiprocessing context to launch the workers created |
| 662 | using the multiprocessing.get_context('start method') API. This |
| 663 | object should provide SimpleQueue, Queue and Process. |
| 664 | initializer: A callable used to initialize worker processes. |
| 665 | initargs: A tuple of arguments to pass to the initializer. |
| 666 | max_tasks_per_child: The maximum number of tasks a worker process |
| 667 | can complete before it will exit and be replaced with a fresh |
| 668 | worker process. The default of None means worker process will |
| 669 | live as long as the executor. Requires a non-'fork' mp_context |
| 670 | start method. When given, we default to using 'spawn' if no |
| 671 | mp_context is supplied. |
| 672 | """ |
| 673 | _check_system_limits() |
| 674 | |
| 675 | if max_workers is None: |
| 676 | self._max_workers = os.process_cpu_count() or 1 |
| 677 | if sys.platform == 'win32': |
| 678 | self._max_workers = min(_MAX_WINDOWS_WORKERS, |
| 679 | self._max_workers) |
| 680 | else: |
| 681 | if max_workers <= 0: |
| 682 | raise ValueError("max_workers must be greater than 0") |
| 683 | elif (sys.platform == 'win32' and |
| 684 | max_workers > _MAX_WINDOWS_WORKERS): |
| 685 | raise ValueError( |
| 686 | f"max_workers must be <= {_MAX_WINDOWS_WORKERS}") |
| 687 | |
| 688 | self._max_workers = max_workers |
| 689 | |
| 690 | if mp_context is None: |
| 691 | if max_tasks_per_child is not None: |
| 692 | mp_context = mp.get_context("spawn") |
| 693 | else: |
| 694 | mp_context = mp.get_context() |
| 695 | self._mp_context = mp_context |
| 696 | |
| 697 | # https://github.com/python/cpython/issues/90622 |
| 698 | self._safe_to_dynamically_spawn_children = ( |
| 699 | self._mp_context.get_start_method(allow_none=False) != "fork") |
| 700 | |
| 701 | if initializer is not None and not callable(initializer): |
| 702 | raise TypeError("initializer must be a callable") |
| 703 | self._initializer = initializer |
| 704 | self._initargs = initargs |
| 705 | |
| 706 | if max_tasks_per_child is not None: |
| 707 | if not isinstance(max_tasks_per_child, int): |
| 708 | raise TypeError("max_tasks_per_child must be an integer") |
| 709 | elif max_tasks_per_child <= 0: |
no outgoing calls
no test coverage detected
searching dependent graphs…