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
deprecate the asyncio child watchers system and policy system #94597
Comments
Some background to this proposed deprecation: This is a more comprehensive version of #82772 @serhiy-storchaka proposed deprecating
@asvetlov noted that
|
We are in dire need of more asyncio experts. @1st1 this isn't urgent but would be nice to have your perspective in time to do this in 3.12. |
For 3.12 IMO we should deprecate |
We discussed this at the sprint and we agree that there are many things wrong with the child watchers and the policy system. Deprecating child watchers: @1st1 thinks these should be done per loop (like uvloop does), not globally by the policy. Much more discussion on this topic is already in #82772. Bottom line, we agree to deprecate it, details remain to be seen. Deprecating policies: Yes please. The policies no longer serve a real purpose. Loops are always per thread, there is no need to have a "current loop" when no loop is currently running. The only thing we still need is a loop factory, so perhaps instead of an API for getting/setting a global "policy", we could have an API for getting/setting a global "loop factory". I'm fine with the We should totally deprecate |
I disagree, that's the most painful part of the policy system that I'm looking to deprecate here in favor of passing an explicit |
What exactly is most painful? That there's a global default for something? To me the painful thing is that the policy system is over-engineered, you have to create a class that overrides I totally agree that most people should use |
I discussed this with Yury and he convinced me that we don't need a global loop factory. Instead we should just have a We still have to come up with a way to transition to a world where child watching is per-loop instead of global though. |
Good news. @1st1 has a simple refactoring of PidfdChildWatcher that makes it independent from the main loop -- just like ThreadedChildWatcher. Once that is merged (PR is forthcoming) we can also merge @kumaraditya303's PR GH-98024, and then we can start deprecating all other child watcher implementations. We can then also deprecate set_child_watcher() (both the asyncio function and the policy method) and eventually we can move the child watcher out of the policy. There's some hand-waving here because in theory people could subclass the default policy class and override get_child_watcher() to construct their own child watcher -- we'll have to deprecate that too somehow. But all this builds a road to a world where policies are no longer needed and eventually no longer exist. |
@gvanrossum I have a PR for Pidfdchildwatcher already #94184 |
It would also be good for the child watchers to be responsible for calling the callback on the event loop thread. Currently the callback needs to defensively call Eg cpython/Lib/asyncio/unix_events.py Line 227 in 282edd7
|
I just read the comments in GH-93453: "Make get_event_loop() an alias of get_running_loop()". This makes me want to go slow with the whole "deprecate policies" part. (I am still fine with deprecating watchers ASAP.) Maybe we could start by deprecating just |
Let's deprecate child watchers first and then we can think about policy since it will require more discussion. |
…LoopChildWatcher` child watchers (#98089)
Maybe we can also deprecate set_child_watcher now? |
But then wouldn't they also expect the watcher they set to be used? Who knows, we need to do some searching. A possible approach would be to deprecate get_child_watcher() and set_child_watcher() but keep their implementation the same, but also stop calling get_child_watcher() in _make_subprocess_transport(). (Arguably if we do this, we should simplify the implementation and always set up a ThreadedChildWatcher in _init_watcher().) |
Searching for set_child_watcher I found gbulb, a library that integrates the GLib main event loop with asyncio. (I actually found glibcoro first, and its README mentions gbulb.) The importance of this find is that gbulb defines its own child watcher class that integrates with the GLib event loop. They also have a custom policy that manages this watcher, and (of course) a custom event loop. I have a feeling they really need to use their custom watcher in their event loop, because of how GLib works (although I don't know anything about GLib). I'm guessing in the long run they can refactor their code to avoid using get/set_child_watcher, but the deprecation might be inconvenient for them. (Then again they override the policy methods so they wouldn't get the deprecation warnings.) This is the first non-trivial mention of set_event_handler I've found (there are lots of dummies and copies around -- a lot of people somehow emulate asyncio). |
There's also an intriguing custom watcher in chaperone but this package appears unmaintained (last commits in 2016). It appears a modified clone of FastChildWatcher. |
* main: Minor edits to the Descriptor HowTo Guide (pythonGH-24901) Fix link to Lifecycle of a Pull Request in CONTRIBUTING (python#98102) pythonGH-94597: deprecate `SafeChildWatcher`, `FastChildWatcher` and `MultiLoopChildWatcher` child watchers (python#98089) Auto-cancel old builds when new commit pushed to branch (python#98009) pythongh-95011: Migrate syslog module to Argument Clinic (pythonGH-95012)
* main: (5519 commits) Minor edits to the Descriptor HowTo Guide (pythonGH-24901) Fix link to Lifecycle of a Pull Request in CONTRIBUTING (python#98102) pythonGH-94597: deprecate `SafeChildWatcher`, `FastChildWatcher` and `MultiLoopChildWatcher` child watchers (python#98089) Auto-cancel old builds when new commit pushed to branch (python#98009) pythongh-95011: Migrate syslog module to Argument Clinic (pythonGH-95012) pythongh-68686: Retire eptag ptag scripts (python#98064) pythongh-97922: Run the GC only on eval breaker (python#97920) GitHub Workflows security hardening (python#96492) Add `@ezio-melotti` as codeowner for `.github/`. (python#98079) pythongh-97913 Docs: Add walrus operator to the index (python#97921) [doc] Fix broken links to C extensions accelerating stdlib modules (python#96914) pythongh-97822: Fix http.server documentation reference to test() function (python#98027) pythongh-91052: Add PyDict_Unwatch for unwatching a dictionary (python#98055) pythonGH-98023: Change default child watcher to PidfdChildWatcher on supported systems (python#98024) pythonGH-94182: Run the PidfdChildWatcher on the running loop (python#94184) pythongh-92886: make test_ast pass with -O (assertions off) (pythonGH-98058) pythongh-92886: make test_coroutines pass with -O (assertions off) (pythonGH-98060) pythongh-57179: Add note on symlinks for os.walk (python#94799) pythongh-94808: Fix regex on exotic platforms (python#98036) pythongh-90085: Remove vestigial -t and -c timeit options (python#94941) ...
We need a better plan for this, here's my plan:
|
…`MultiLoopChildWatcher` child watchers (python#98089)
Are you thinking of doing all of these in 3.12 except the final checkbox? If so we should probably do "asyncio ignores set child watcher and instead always uses PidfdChildWatcher or ThreadedChildWatcher" next, before "Deprecate all child watcher configuration methods and functions ..." |
I first want to get agreement on whether we should raise |
This is the next step for deprecating child watchers. Until we've removed the API completely we have to use it, so this PR is mostly suppressing a lot of warnings when using the API internally. Once the child watcher API is totally removed, the two child watcher implementations we actually use and need (Pidfd and Thread) will be turned into internal helpers.
I think the remaining three tasks cannot be done until 3.14. |
This is done for 3.12, now onto the policy minefield. |
* main: (31 commits) pythongh-95913: Move subinterpreter exper removal to 3.11 WhatsNew (pythonGH-98345) pythongh-95914: Add What's New item describing PEP 670 changes (python#98315) Remove unused arrange_output_buffer function from zlibmodule.c. (pythonGH-98358) pythongh-98174: Handle EPROTOTYPE under macOS in test_sendfile_fallback_close_peer_in_the_middle_of_receiving (python#98316) pythonGH-98327: Reduce scope of catch_warnings() in _make_subprocess_transport (python#98333) pythongh-93691: Compiler's code-gen passes location around instead of holding it on the global compiler state (pythonGH-98001) pythongh-97669: Create Tools/build/ directory (python#97963) pythongh-95534: Improve gzip reading speed by 10% (python#97664) pythongh-95913: Forward-port int/str security change to 3.11 What's New in main (python#98344) pythonGH-91415: Mention alphabetical sort ordering in the Sorting HOWTO (pythonGH-98336) pythongh-97930: Merge with importlib_resources 5.9 (pythonGH-97929) pythongh-85525: Remove extra row in doc (python#98337) pythongh-85299: Add note warning about entry point guard for asyncio example (python#93457) pythongh-97527: IDLE - fix buggy macosx patch (python#98313) pythongh-98307: Add docstring and documentation for SysLogHandler.createSocket (pythonGH-98319) pythongh-94808: Cover `PyFunction_GetCode`, `PyFunction_GetGlobals`, `PyFunction_GetModule` (python#98158) pythonGH-94597: Deprecate child watcher getters and setters (python#98215) pythongh-98254: Include stdlib module names in error messages for NameErrors (python#98255) Improve speed. Reduce auxiliary memory to 16.6% of the main array. (pythonGH-98294) [doc] Update logging cookbook with an example of custom handling of levels. (pythonGH-98290) ...
FWIW it seems that Jupyter has a legitimate reason to override the default policy (with another one of the predefined ones), see #93453 (comment). |
The WindowsSelectorEventLoopPolicy shouldn't be needed with tornado 6.2 where it runs a selector in a background thread so the main event loop can be the ProactorEventLoop |
It seems @1st1 is in favor of deprecating the rest of the policy system: https://twitter.com/1st1/status/1711007413275365590?t=PGAYW5447_2JZdgiIsu6eQ&s=19 can we do this for 3.13? |
I am fine with that. But I am not someone with a lot of time for it. In 3.13 all we need is some deprecations. Can you help with that? |
@gvanrossum I can definitely help adding deprecations! |
This is needed to pave the way for deprecating and eventually killing the event loop policy system (which is over-engineered and rarely used).
I want to cleanup the calls to def teardownModule():
asyncio.set_event_loop_policy(None) this is now possible for tests that just use |
Deprecate the child watchers system and the policy system in favour of
asyncio.Runner(loop_factory=asyncio.ProactorEventLoop/asyncio.SelectorEventLoop/uvloop.new_event_loop)
that would be deprecating:
I'd also like to introduce a new API:
asyncio.EventLoop
implemented as:asyncio.new_event_loop()
will issue a DeprecationWarning if the current policy is not the default policy, and then in 3 releases become an alias ofasyncio.EventLoop
Originally posted by @graingert in #93896 (comment)
AbstractChildWatcher
#99386The text was updated successfully, but these errors were encountered: