-
-
Notifications
You must be signed in to change notification settings - Fork 32.4k
bpo-32596: Lazy import concurrent.futures.process and thread #5241
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
Conversation
Using module __getattr__ (PEP 562)
|
||
|
||
def __getattr__(name): | ||
global ProcessPoolExecutor, ThreadPoolExecutor |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't follow why do you need globals here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
>>> 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Neat trick!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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
global
statement must not be defined as formal parameters or in afor
loop control target,class
definition, function definition,import
statement, 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if/elif/else
would be a little faster maybe?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
dis
shows exactly same bytecode for both.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok
https://bugs.python.org/issue32596