Allow factory kwargs
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.
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.
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
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.
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.
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.
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).
Any intent to merge this soon ?