4 ms·
Ask HN: Ways to deal with Python 3.11 breaking change to asyncio
AFAICT 3.11 requires your code to call asyncio.run(), whereas earlier versions (for some definition of "earlier") required you to inject your coroutines and then call loop.run_forever().
Basically it smells to me like this is going to require two distinct main()s. This is ugly. How do I make it not butt ugly and minimize the general odor?
- m3047 4y agoLet me break it down for you: Suppose I run asyncio.start_server() and I want it to run forever. What am I supposed to asyncio.gather()) on without making stuff up? [Edit] Production code or it didn't happen.
- m3047 4y agoGiven this: server = await asyncio.start_server( context.handle_requests, str(config.host), config.port, limit=MAX_READ_SIZE ) as stated, you can't use gather(). There are sleight of hand "coincidences", such as waiting on a watchdog which runs forever. I stumbled on this as something that works: useless_lock = asyncio.Lock() while True: await useless_lock.acquire() Which demonstrates that the following is, ahem, sleight of hand: async with server: await server.serve_forever() although supposedly it guarantees some cleanup which I don't care about. Both options respond identically (at least with 3.11.0) to ^C. I reiterate that serve_forever() is not in 3.6.
- deleted 4y ago[deleted]
- tony-allan 4y agoAn example and references to the 3.11 changelog would be helpful...
- m3047 4y agoI'll be more brazen and say I would have expected some working, production code examples by now. What I've got is someone throwing it over the wall: ok, thanks, I guess. I'd rather know than not. But the code is smelly, internally it would appear to be failing because it tried to pass a loop kwarg which another part of it doesn't recognize: I didn't pass that arg. From what I can see so far asyncio.gather() would seem to be the canonical refactor. I'm not sure that I'm down with the philosophy of the loop stopping running AT ALL unless I ask for it. I've got long-running processes. I spew stack traces from within coroutines, and if the situation is dire enough I call stop() myself. I always thought that being able to leave coroutines in the queue when the loop isn't running was a feature, not a bug.
- m3047 4y ago> An example and references to the 3.11 changelog would be helpful... Can't tell from that remark whether you're asking or telling...
- gabrielsroka 4y agoget_event_loop was deprecated in Python 3.10 loop = asyncio.get_event_loop() loop.run_until_complete(main()) https://docs.python.org/3.10/library/asyncio-eventloop.html https://docs.python.org/3.10/library/asyncio-eventloop.html
- seanhunter 4y agoYou don’t need two different mains. My asyncio code runs just fine on both and didn’t require changes when moving from 3.10 to 3.11 possibly because the way I always do it is asyncio.run(main()) from the body of the code (“actual main”) to an async def main async callable and the last real line of that is pretty much always just an asyncio.gather over a bunch of other stuff that I want to run. My understanding is that’s been the recommended method for a very long time rather than get_event_loop or run_forever or anything like that. edit: that is to say, asyncio.run() may be required now but the method of injecting coroutines and then doing run_forever was definitely not required before. Asyncio.run was available before 3.11.