filesystem_spec icon indicating copy to clipboard operation
filesystem_spec copied to clipboard

Asyncio.get_event_loop does not work with fsspec.asyn.sync

Open omerXfaruq opened this issue 3 years ago • 6 comments

Hello, the example below does not work, while I believe it should work.

import asyncio
import fsspec.asyn

print("yey")
loop = asyncio.get_event_loop()
fsspec.asyn.sync(loop, asyncio.sleep, delay=5)
print("yey")

After printing out the first "yey" the program does not output anything, and when it is stopped, it outputs this:

yey
Traceback (most recent call last):
  File "F:\SecondaryDownloads\git_repos\gradio\dev_mode.py", line 7, in <module>
    print("yey")
  File "F:\SecondaryDownloads\git_repos\gradio\venv\lib\site-packages\fsspec\asyn.py", line 54, in sync
    if event.wait(1):
  File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.9_3.9.2800.0_x64__qbz5n2kfra8p0\lib\threading.py", line 574, in wait
    signaled = self._cond.wait(timeout)
  File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.9_3.9.2800.0_x64__qbz5n2kfra8p0\lib\threading.py", line 316, in wait
    gotit = waiter.acquire(True, timeout)
KeyboardInterrupt

However, it works perfectly when fsspec.asyn.get_loop is used.

import asyncio
import fsspec.asyn

print("yey")
loop = fsspec.asyn.get_loop()
fsspec.asyn.sync(loop, asyncio.sleep, delay=5)
print("yey")

omerXfaruq avatar Jun 10 '22 16:06 omerXfaruq

I am unsure why it does not raise an error, and waits indefinitely. It should raise an error according to this line

omerXfaruq avatar Jun 13 '22 15:06 omerXfaruq

You are not calling sync from within a loop, you are calling sync with a loop in the same thread, and then blocking waiting on a thread event to be set. The event wait and the event loop cannot progress at the same time, so you deadlock.

martindurant avatar Jun 13 '22 15:06 martindurant

Then what about this situation, is it still not from a loop?

from fastapi import FastAPI

app = FastAPI()


@app.get("/")
async def main():
    import asyncio
    import fsspec.asyn
    print("yey")
    print(asyncio.get_running_loop())
    loop = asyncio.get_event_loop()
    fsspec.asyn.sync(loop, asyncio.sleep, delay=5)
    print("yey")

image

omerXfaruq avatar Jun 13 '22 17:06 omerXfaruq

Ah, well if you are in a loop already, you should not be using sync at all. All async backends offer async versions of their methods, and you would simply await them.

martindurant avatar Jun 13 '22 17:06 martindurant

Ah, well if you are in a loop already, you should not be using sync at all. All async backends offer async versions of their methods, and you would simply await them.

Well, this is actually a use-case that is missing in python. For example in Gradio we allow users to launch the server in sync functions for ease of use, and later need async calls.

omerXfaruq avatar Jun 14 '22 03:06 omerXfaruq

asyncio.get_event_loop() is being made an alias of asyncio.get_running_loop() on python 3.12

graingert avatar Jun 17 '22 23:06 graingert