Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

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

get event loop for the fastapi #825

Closed
timofei-durakov opened this issue Dec 30, 2019 · 9 comments
Closed

get event loop for the fastapi #825

timofei-durakov opened this issue Dec 30, 2019 · 9 comments
Labels
question Question or problem question-migrate

Comments

@timofei-durakov
Copy link

timofei-durakov commented Dec 30, 2019

Is there any way to get event or provide event loop for the fast api app. I would like to run low level tcp server(asyncio low-level protocols) and fast api within the same process. So I need to reuse the same event loop for both of them. Is it possible doing somehow?

@timofei-durakov timofei-durakov added the question Question or problem label Dec 30, 2019
@prostomarkeloff
Copy link
Contributor

Yes, i think it's possible. You can start the fastapi application by hypercorn.
Source: https://pgjones.gitlab.io/hypercorn/api_usage.html

Your code should look like that:

# some definitons

loop = asyncio.get_event_loop()

loop.create_task(serve(app, config))  # run fastapi
loop.create_task(my_super_app()) # run your app
loop.run_forever()  # start event loop

I don't know how to do something like that with uvicorn.

@dmontagu
Copy link
Collaborator

dmontagu commented Dec 30, 2019

Unfortunately it looks like uvicorn doesn't expose a great way to specify the specific event loop instance to use. However, in my experience uvicorn is substantially faster than hypercorn (I've seen 2-4x performance improvements in some cases for certain streaming endpoints), so may be worth a little extra pain to make things work. Especially if your TCP server is going to be interacting with the python event loop with any substantial frequency (which would not surprise me).

You can get the event loop being used by FastAPI by calling asyncio.get_running_loop() in a function that will be called with that event loop; e.g., inside an async def server startup event.

If possible, my recommendation would be to put the startup of your tcp server into a FastAPI startup event so it can run in the same uvicorn loop. This would probably be the easiest way to get things to work.

If you need to start the TCP server prior to the FastAPI server for some reason, it will probably be more complicated, but likely not impossible.

@euri10
Copy link
Contributor

euri10 commented Dec 30, 2019 via email

@dmontagu
Copy link
Collaborator

dmontagu commented Dec 30, 2019

@euri10 A cursory look at uvicorn/config.py made me think this would cause an issue:

https://github.com/encode/uvicorn/blob/abd68704ea75cdbac8ffb1b5c59578a17a716a56/uvicorn/config.py#L319

    def setup_event_loop(self):
        loop_setup = import_from_string(LOOP_SETUPS[self.loop])
        if loop_setup is not None:
            loop_setup()

In particular, that function is called by uvicorn.run, and LOOP_SETUPS only has string keys. So I don't think you are supposed to pass a loop instance to the uvicorn config, at least not as the loop keyword argument?

Is there a different way to make this work?

@euri10
Copy link
Contributor

euri10 commented Dec 30, 2019

encode/uvicorn#510 the last test https://github.com/encode/uvicorn/blob/a9fcfb7051757cfe25e7b289f829507133110f16/tests/test_main.py#L109

uses the pattern I'm thinking of, the fact it's in threads is irrelevant in this case of course

@dmontagu
Copy link
Collaborator

Cool, thanks for looking into that @euri10.

@timofei-durakov if you want to configure the event loop yourself, based on the example @euri10 provided it should look like:

config = Config(app=fastapi_app, loop=loop_instance)
server = Server(config=config)
server.run()

I haven't verified that will work though.

That said, if you don't want to figure out precisely how to manually set up the event loop for maximum performance, it may still be easier (if possible) to set up the TCP server from inside a startup event of the FastAPI server.

@tiangolo
Copy link
Owner

Thanks for all the help here everyone! 🙇‍♂️ 🍰

@timofei-durakov does that solve your issue?

@github-actions
Copy link
Contributor

Assuming the original issue was solved, it will be automatically closed now. But feel free to add more comments or create new issues.

@lsaint
Copy link

lsaint commented Aug 31, 2020

@dmontagu

If possible, my recommendation would be to put the startup of your tcp server into a FastAPI startup event so it can run in the same uvicorn loop. This would probably be the easiest way to get things to work.

let's say, i have a new event loop, to run a function every seconds, how to add it in this way?

@tiangolo tiangolo changed the title [QUESTION] get event loop for the fastapi get event loop for the fastapi Feb 24, 2023
@tiangolo tiangolo reopened this Feb 28, 2023
Repository owner locked and limited conversation to collaborators Feb 28, 2023
@tiangolo tiangolo converted this issue into discussion #7876 Feb 28, 2023

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
question Question or problem question-migrate
Projects
None yet
Development

No branches or pull requests

6 participants