-
-
Notifications
You must be signed in to change notification settings - Fork 34.7k
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,5 +15,36 @@ | |
| Executor, | ||
| wait, | ||
| as_completed) | ||
| from concurrent.futures.process import ProcessPoolExecutor | ||
| from concurrent.futures.thread import ThreadPoolExecutor | ||
|
|
||
| __all__ = ( | ||
| 'FIRST_COMPLETED', | ||
| 'FIRST_EXCEPTION', | ||
| 'ALL_COMPLETED', | ||
| 'CancelledError', | ||
| 'TimeoutError', | ||
| 'BrokenExecutor', | ||
| 'Future', | ||
| 'Executor', | ||
| 'wait', | ||
| 'as_completed', | ||
| 'ProcessPoolExecutor', | ||
| 'ThreadPoolExecutor', | ||
| ) | ||
|
|
||
|
|
||
| def __dir__(): | ||
| return __all__ + ('__author__', '__doc__') | ||
|
|
||
|
|
||
| def __getattr__(name): | ||
| global ProcessPoolExecutor, ThreadPoolExecutor | ||
|
|
||
| if name == 'ProcessPoolExecutor': | ||
| from .process import ProcessPoolExecutor | ||
| return ProcessPoolExecutor | ||
|
|
||
| if name == 'ThreadPoolExecutor': | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok |
||
| from .thread import ThreadPoolExecutor | ||
| return ThreadPoolExecutor | ||
|
|
||
| raise AttributeError(f"module {__name__} has no attribute {name}") |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| ``concurrent.futures`` imports ``ThreadPoolExecutor`` and | ||
| ``ProcessPoolExecutor`` lazily (using :pep:`562`). | ||
| It makes ``import asyncio`` about 15% faster because asyncio | ||
| uses only ``ThreadPoolExecutor`` by default. |
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, becausefutureshasProcessPoolExecutornow.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.
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
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