Consider the following code:
import asyncio
sem: asyncio.Semaphore = asyncio.Semaphore(2)
async def async_run() -> None:
async def async_task() -> None:
async with sem:
await asyncio.sleep(1)
print('spam')
await asyncio.gather(*[async_task() for _ in range(3)])
asyncio.run(async_run())
Run with Python 3.10.6 (Fedora 35), it works just like in the schoolbook.
However, when I run it with Python 3.8.10 (Ubuntu 20.04), I get the following error:
Traceback (most recent call last):
File "main.py", line 21, in <module>
asyncio.run(async_run())
File "/usr/lib/python3.8/asyncio/runners.py", line 44, in run
return loop.run_until_complete(main)
File "/usr/lib/python3.8/asyncio/base_events.py", line 616, in run_until_complete
return future.result()
File "main.py", line 18, in async_run
print(future_entry_index, await future_entry)
File "/usr/lib/python3.8/asyncio/tasks.py", line 619, in _wait_for_one
return f.result() # May raise f.exception().
File "main.py", line 11, in async_task
async with sem:
File "/usr/lib/python3.8/asyncio/locks.py", line 97, in __aenter__
await self.acquire()
File "/usr/lib/python3.8/asyncio/locks.py", line 496, in acquire
await fut
RuntimeError: Task <Task pending name='Task-4' coro=<async_run.<locals>.async_task() running at main.py:11> cb=[as_completed.<locals>._on_completion() at /usr/lib/python3.8/asyncio/tasks.py:606]> got Future <Future pending> attached to a different loop
It's async with sem
line and the Semaphore
object that cause the error. Without it, everything works without errors, but not the way I want it to.
I can't provide the loop
parameter anywhere, for even where it's allowed, it has been deprecated since Python 3.8 and removed in Python 3.10.
How to make the code work with Python 3.8?
Update. A glimpse at the asyncio
code showed that the Python versions differ a lot. However, the Semaphores can't be just broken in 3.8, right?