-
-
Notifications
You must be signed in to change notification settings - Fork 33.4k
gh-140995: [asyncio] Add high-level API to run functions in subinterpreters #140996
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
|
Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool. If this change has little impact on Python users, wait for a maintainer to apply the |
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.
This needs to be skipped when the implementation doesn't support subinterpreters. You probably just want something like:
try:
from asyncio import run_in_subinterpreter
except ImportError:
raise unittest.SkipTest("subinterpreters not supported")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.
Thank you, fixed
Lib/asyncio/__init__.py
Outdated
| from .timeouts import * | ||
| from .threads import * | ||
| from .transports import * | ||
| from .subinterpreters import * |
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.
You also need to handle other implementations here. If this fails with an ImportError, it shouldn't prevent the whole module from being imported.
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.
Thank you, fixed
Lib/asyncio/subinterpreters.py
Outdated
| worker_count: int | None = None | ||
| if n: | ||
| worker_count = max(1, n // 2) | ||
| with InterpreterPoolExecutor(max_workers=worker_count) as pool: |
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 we only want one worker?
Lib/asyncio/subinterpreters.py
Outdated
| worker_count = max(1, n // 2) | ||
| with InterpreterPoolExecutor(max_workers=worker_count) as pool: | ||
| future = pool.submit(func, *args, **kwargs) | ||
| return future.result() No newline at end of file |
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.
As far as I can tell, this never yields to the event loop, so it doesn't let anything else run while the subinterpreter executes (defeating the point of this API entirely).
I think you want to use something like loop.run_in_executor or asyncio.to_thread. The event loop needs to yield while executing the synchronous code in another interpreter. Here's a simple POC:
import asyncio
from concurrent import interpreters
async def run_in_subinterpreter(func):
interp = interpreters.create()
try:
await asyncio.to_thread(interp.call, func)
finally:
interp.close()
def compute_synchronous_stuff():
for n in range(10000):
n ** n
async def work():
print("doing async I/O")
await asyncio.sleep(1)
print("done")
async def main():
task = asyncio.create_task(work())
print("doing sync I/O")
# The task can execute while this is running
await run_in_subinterpreter(compute_synchronous_stuff)
print("done")
await task
asyncio.run(main())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.
Thank you, it was like a blueprint for the issue i created, also changed this to non-blocking implementation
|
Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool. If this change has little impact on Python users, wait for a maintainer to apply the |
|
Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool. If this change has little impact on Python users, wait for a maintainer to apply the |
|
Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool. If this change has little impact on Python users, wait for a maintainer to apply the |
|
Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool. If this change has little impact on Python users, wait for a maintainer to apply the |
|
Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool. If this change has little impact on Python users, wait for a maintainer to apply the |
|
Closing as it was deemed unnecessary |
This PR adds a high-level asynchronous API
asyncio.run_in_subinterpreterfor running Python functionsin subinterpreters. It uses InterpreterPoolExecutor internally and chooses the number of subinterpreters
based on the CPU count.
Motivation:
Example usage:
Tests:
and complex objects.