What is uvicorn.run()?
uvicorn.run() is the programmatic interface to Uvicorn, Python's lightning-fast ASGI web server. Unlike the command-line interface, it allows you to start and configure your server directly from Python code, giving you complete control over server lifecycle and configuration.
Perfect for production deployments, testing environments, and applications that need dynamic server configuration, uvicorn.run() is the go-to choice for modern Python web applications built with FastAPI, Starlette, and other ASGI frameworks.
Quick Start
Get up and running with uvicorn.run() in seconds:
import uvicorn
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def read_root():
return {"message": "Hello, World!"}
if __name__ == "__main__":
uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)
That's it! Your ASGI application is now running with automatic reloading enabled for development.
Parameters Reference
Configure every aspect of your server with these comprehensive parameters:
app
str | ASGI AppYour ASGI application. Can be a string in "module:attribute" format or the application object directly.
host
strBind socket to this host. Use "0.0.0.0" to make the server available externally. Default: "127.0.0.1"
port
intBind socket to this port. Default: 8000
reload
boolEnable auto-reload for development. Watches for file changes and restarts the server automatically.
log_level
strLogging level: "critical", "error", "warning", "info", "debug", "trace". Default: "info"
ssl_keyfile
strSSL key file path for HTTPS support.
ssl_certfile
strSSL certificate file path for HTTPS support.
workers
intNumber of worker processes. Only available when not using reload.
Real-World Examples
Production Configuration
import uvicorn
import os
if __name__ == "__main__":
uvicorn.run(
"app.main:app",
host="0.0.0.0",
port=int(os.getenv("PORT", 8000)),
workers=4,
log_level="warning",
access_log=False,
ssl_keyfile="./ssl/key.pem",
ssl_certfile="./ssl/cert.pem"
)
Development with Auto-Reload
import uvicorn
if __name__ == "__main__":
uvicorn.run(
"app.main:app",
host="127.0.0.1",
port=8000,
reload=True,
reload_dirs=["./app"],
log_level="debug"
)
Advanced Configuration with Config Object
import uvicorn
from uvicorn.config import Config
from uvicorn.server import Server
async def run_server():
config = Config(
"app.main:app",
host="0.0.0.0",
port=8000,
log_level="info",
access_log=True,
use_colors=True
)
server = Server(config)
await server.serve()
if __name__ == "__main__":
import asyncio
asyncio.run(run_server())
Testing Environment
import uvicorn
import threading
import time
def start_test_server():
uvicorn.run(
"tests.app:app",
host="127.0.0.1",
port=8001,
log_level="critical",
access_log=False
)
# Start server in background for testing
server_thread = threading.Thread(target=start_test_server, daemon=True)
server_thread.start()
time.sleep(1) # Wait for server to start
# Run your tests here
Best Practices
Performance & Security
- Use multiple workers in production for CPU-bound tasks
- Disable access logs in production for better performance
- Use environment variables for configuration
- Enable SSL/TLS for production deployments
- Set appropriate log levels for different environments
- Use reload only in development environments
- Configure proper host binding (0.0.0.0 for external access)
- Monitor server performance with proper logging
Development Tips
- Use reload_dirs to watch specific directories for changes
- Set debug log level during development
- Use different ports for different services
- Keep development and production configs separate
Common Patterns
Environment-Based Configuration
import uvicorn
import os
def get_config():
if os.getenv("ENVIRONMENT") == "production":
return {
"host": "0.0.0.0",
"port": int(os.getenv("PORT", 8000)),
"workers": int(os.getenv("WORKERS", 4)),
"log_level": "warning",
"access_log": False
}
else:
return {
"host": "127.0.0.1",
"port": 8000,
"reload": True,
"log_level": "debug"
}
if __name__ == "__main__":
config = get_config()
uvicorn.run("app.main:app", **config)
Graceful Shutdown
import uvicorn
import signal
import asyncio
class GracefulServer:
def __init__(self):
self.server = None
self.should_exit = False
async def run(self):
config = uvicorn.Config("app.main:app", host="0.0.0.0", port=8000)
self.server = uvicorn.Server(config)
# Setup signal handlers
for sig in (signal.SIGTERM, signal.SIGINT):
signal.signal(sig, self.signal_handler)
await self.server.serve()
def signal_handler(self, signum, frame):
print(f"Received signal {signum}")
self.should_exit = True
if self.server:
self.server.should_exit = True
if __name__ == "__main__":
server = GracefulServer()
asyncio.run(server.run())