Skip to content
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

async support #691

Open
rraammiinn opened this issue May 19, 2023 · 1 comment
Open

async support #691

rraammiinn opened this issue May 19, 2023 · 1 comment

Comments

@rraammiinn
Copy link

can you add async support to it ?
I tried to use async-eel module but it didn't work .

@ajmirsky
Copy link

ajmirsky commented Aug 23, 2023

eel uses greenlets which was a python library for coroutines before asyncio was introduced. so using greenlet coroutines instead of asyncio coroutines is probably the cleanest approach.

But if you're dependent on an already existing async library, you can spawn eel into a greenlet (by passing block=False to eel.start) and then run your asyncio coroutines. Since you're running two different types of coroutines, make sure you "await" the greenlets too:


async def my_async_function():
    print("my async function is running")
    await asyncio.sleep(0) # allows other asyncio coroutines time to run
    eel.sleep(0)  # allows the eel greenlet coroutines time to run

def main()
    eel.start(...., block=False) 

    asyncio.run(my_async_function())

The alternative is to run your async functions in a separate thread (I find this cleaner) and then let eel run its greenlets in the main thread.

from threading import Thread

class AsyncioThread(Thread):
    daemon = True
    def __init__(self):
        super().__init__()
        self.loop = get_event_loop()

    async def my_async_function():
        print("running my async function")
        await asyncio.sleep(1)
        
    async def launch(self):
        task1 = self.loop.create_task(self.my_async_function())
        await asyncio.gather(task1)

    def run(self):
        self.loop.run_until_complete(self.launch())


def main():

    asyncio_thread = AsyncioThread()
    asyncio_thread.start()
    
    eel.start(...)

for either method, if you need any @eel.expose function to interact with your async functions, use the threadsafe versions -- run_coroutine_threadsafe and call_soon_threadsafe --since eel will be calling from a separate thread. keep in mind that these methods don't necessarily use the event loop's exception handling so you might need to handle those cases separately.

also, it is good practice to clean up your coroutines before exiting the app/thread, so in the close_callback function passed to eel.start, you should call cancel() on each task by holding on to a reference to each task (eg self.task_list.append(task1)) or using a method to find all running tasks in an event loop.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants