uvicorn icon indicating copy to clipboard operation
uvicorn copied to clipboard

Allow factory kwargs

Open SaravananSathyanandhaQC opened this issue 1 year ago • 7 comments

Summary

Addresses https://github.com/encode/uvicorn/discussions/2377 and #1644

This PR allows passing factory_kwargs to all workers when using uvicorn.run. This is more flexible than using environment variables because it means you can

Checklist

  • [x] I understand that this PR may be closed in case there was no previous discussion. (This doesn't apply to typos!)
  • [x] I've added a test for each change that was introduced, and I tried as much as possible to make a single atomic change.
  • [ ] I've updated the documentation accordingly.

SaravananSathyanandhaQC avatar Aug 20 '24 13:08 SaravananSathyanandhaQC

in my test,i can not get worker_kwargs as what i expect. i have tow py file, run.py and a.py. run.py as flow

from pathlib import Path
import uvicorn
import a
app = a.app
print("-------- queue  ----------")
if __name__ == '__main__':
    max_workers = 4
    uvicorn.run(f"{Path(a.__file__).stem}:app", host='0.0.0.0', port=8000, reload=True,
        worker_kwargs={"shared_queue": [1, 2, 3, 4]})

a.py as follow

from fastapi import FastAPI
app = FastAPI()

@app.get("/city/{city_id}")
def get_city(city_id: str):
    return {"city_id": city_id, "app": dir(app)}

curl

result

{
  "city_id": "123",
  "app": [
    "__call__",
    "__class__",
    "__delattr__",
    "__dict__",
    "__dir__",
    "__doc__",
    "__eq__",
    "__format__",
    "__ge__",
    "__getattribute__",
    "__gt__",
    "__hash__",
    "__init__",
    "__init_subclass__",
    "__le__",
    "__lt__",
    "__module__",
    "__ne__",
    "__new__",
    "__reduce__",
    "__reduce_ex__",
    "__repr__",
    "__setattr__",
    "__sizeof__",
    "__str__",
    "__subclasshook__",
    "__weakref__",
    "add_api_route",
    "add_api_websocket_route",
    "add_event_handler",
    "add_exception_handler",
    "add_middleware",
    "add_route",
    "add_websocket_route",
    "api_route",
    "build_middleware_stack",
    "contact",
    "debug",
    "delete",
    "dependency_overrides",
    "description",
    "docs_url",
    "exception_handler",
    "exception_handlers",
    "extra",
    "get",
    "head",
    "host",
    "include_router",
    "license_info",
    "middleware",
    "middleware_stack",
    "mount",
    "on_event",
    "openapi",
    "openapi_schema",
    "openapi_tags",
    "openapi_url",
    "openapi_version",
    "options",
    "patch",
    "post",
    "put",
    "redoc_url",
    "root_path",
    "root_path_in_servers",
    "route",
    "router",
    "routes",
    "separate_input_output_schemas",
    "servers",
    "setup",
    "state",
    "summary",
    "swagger_ui_init_oauth",
    "swagger_ui_oauth2_redirect_url",
    "swagger_ui_parameters",
    "terms_of_service",
    "title",
    "trace",
    "url_path_for",
    "user_middleware",
    "version",
    "webhooks",
    "websocket",
    "websocket_route"
  ]
}

in my opinion,i can get shared_queue in app but not. i use what you changed code.

lekeeith avatar Aug 22 '24 08:08 lekeeith

The option only applies when you use the factory option (maybe I should call it factory_kwargs), since then you have a function to return the app, and that function can get kwargs passed. If you use a single app like this then it will not work, it doesn't try to add attributes to the app itself (though that could be an alternate solution too).

If you made your a.py look like the following:

from fastapi import FastAPI

def app_creator(shared_queue = None):
    app = FastAPI()

    @app.get("/city/{city_id}")
    def get_city(city_id: str):
        return {"city_id": city_id, "shared_queue": shared_queue}

    return app

you should see the shared_queue passed.

If you actually intend to use this as a shared queue between workers that has items added/removed (as the variable name suggests at least) you should use a shared memory list or a SyncManager list

SaravananSathyanandhaQC avatar Aug 23 '24 09:08 SaravananSathyanandhaQC

I agree naming the parameter factory_kwargs would be better.

I was going to make that PR myself when I saw it already existed. This feature is a must for being able to use uvicorn.run programmatically without having to resort to workarounds like environment variables to simply pass configuration values to the app.

So, bumping here, hoping this gets merged soon.

hchargois-ipsos avatar Jun 05 '25 17:06 hchargois-ipsos

I've updated it to factory_kwargs and added those type hints. I continue to work around this with env vars, but this PR would make my code a lot cleaner.

SaravananSathyanandhaQC avatar Jun 05 '25 19:06 SaravananSathyanandhaQC

Merging this would be a must.

I looked at the changes and find them very clean and straightforward.

Can't wait to use this missing feature.

guillaume-mueller avatar Jul 18 '25 16:07 guillaume-mueller

Great work! Simple and clean and it will hopefully get added to the CLI interface as well (only string values ofc, but better than nothing).

MatteoCampinoti94 avatar Jul 20 '25 11:07 MatteoCampinoti94

Any intent to merge this soon ?

guillaume-mueller avatar Oct 21 '25 12:10 guillaume-mueller