bpo-32596: Lazy import concurrent.futures.process and thread#5241
Conversation
Using module __getattr__ (PEP 562)
|
|
||
|
|
||
| def __getattr__(name): | ||
| global ProcessPoolExecutor, ThreadPoolExecutor |
There was a problem hiding this comment.
Don't follow why do you need globals here?
There was a problem hiding this comment.
Once ProcessPoolExecutor is accessed, it's assigned to module global.
Next time, __getattr__ is not called, because futures has ProcessPoolExecutor now.
There was a problem hiding this comment.
>>> import concurrent.futures
>>> concurrent.futures.__dict__.keys()
dict_keys(['__name__', '__doc__', '__package__', '__loader__', '__spec__', '__path__', '__file__', '__cached__', '__builtins__', '__author__', '_base', 'FIRST_COMPLETED', 'FIRST_EXCEPTION', 'ALL_COMPLETED', 'CancelledError', 'TimeoutError', 'BrokenExecutor', 'Future', 'Executor', 'wait', 'as_completed', '__all__', '__dir__', '__getattr__'])
>>> from concurrent.futures import *
>>> concurrent.futures.__dict__.keys()
dict_keys(['__name__', '__doc__', '__package__', '__loader__', '__spec__', '__path__', '__file__', '__cached__', '__builtins__', '__author__', '_base', 'FIRST_COMPLETED', 'FIRST_EXCEPTION', 'ALL_COMPLETED', 'CancelledError', 'TimeoutError', 'BrokenExecutor', 'Future', 'Executor', 'wait', 'as_completed', '__all__', '__dir__', '__getattr__', 'process', 'ProcessPoolExecutor', 'thread', 'ThreadPoolExecutor'])
There was a problem hiding this comment.
Actually, this pattern is explicitly discouraged and my not work in other implementations, see https://docs.python.org/3.7/reference/simple_stmts.html#the-global-statement
Names listed in a
globalstatement must not be defined as formal parameters or in aforloop control target,classdefinition, function definition,importstatement, or variable annotation.
CPython implementation detail: The current implementation does not enforce some of these restrictions, but programs should not abuse this freedom, as future implementations may enforce them or silently change the meaning of the program.
There is however no recommendations on what is the recommended pattern instead.
There was a problem hiding this comment.
@ilevkivskyi Thanks, I didn't know that.
I'll fix it before 3.7b1
| from .process import ProcessPoolExecutor | ||
| return ProcessPoolExecutor | ||
|
|
||
| if name == 'ThreadPoolExecutor': |
There was a problem hiding this comment.
if/elif/else would be a little faster maybe?
There was a problem hiding this comment.
dis shows exactly same bytecode for both.
https://bugs.python.org/issue32596