Skip to content

Commit d71be59

Browse files
authored
✨ Add FastAPI CLI, the new fastapi command (#11522)
1 parent a94ef33 commit d71be59

18 files changed

+376
-165
lines changed

README.md

Lines changed: 44 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -139,18 +139,6 @@ $ pip install fastapi
139139

140140
</div>
141141

142-
You will also need an ASGI server, for production such as <a href="https://www.uvicorn.org" class="external-link" target="_blank">Uvicorn</a> or <a href="https://github.com/pgjones/hypercorn" class="external-link" target="_blank">Hypercorn</a>.
143-
144-
<div class="termy">
145-
146-
```console
147-
$ pip install "uvicorn[standard]"
148-
149-
---> 100%
150-
```
151-
152-
</div>
153-
154142
## Example
155143

156144
### Create it
@@ -211,25 +199,38 @@ Run the server with:
211199
<div class="termy">
212200

213201
```console
214-
$ uvicorn main:app --reload
215-
202+
$ fastapi dev main.py
203+
204+
╭────────── FastAPI CLI - Development mode ───────────╮
205+
│ │
206+
│ Serving at: http://127.0.0.1:8000 │
207+
│ │
208+
│ API docs: http://127.0.0.1:8000/docs │
209+
│ │
210+
│ Running in development mode, for production use: │
211+
│ │
212+
│ fastapi run │
213+
│ │
214+
╰─────────────────────────────────────────────────────╯
215+
216+
INFO: Will watch for changes in these directories: ['/home/user/code/awesomeapp']
216217
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
217-
INFO: Started reloader process [28720]
218-
INFO: Started server process [28722]
218+
INFO: Started reloader process [2248755] using WatchFiles
219+
INFO: Started server process [2248757]
219220
INFO: Waiting for application startup.
220221
INFO: Application startup complete.
221222
```
222223

223224
</div>
224225

225226
<details markdown="1">
226-
<summary>About the command <code>uvicorn main:app --reload</code>...</summary>
227+
<summary>About the command <code>fastapi dev main.py</code>...</summary>
227228

228-
The command `uvicorn main:app` refers to:
229+
The command `fastapi dev` reads your `main.py` file, detects the **FastAPI** app in it, and starts a server using <a href="https://www.uvicorn.org" class="external-link" target="_blank">Uvicorn</a>.
229230

230-
* `main`: the file `main.py` (the Python "module").
231-
* `app`: the object created inside of `main.py` with the line `app = FastAPI()`.
232-
* `--reload`: make the server restart after code changes. Only do this for development.
231+
By default, `fastapi dev` will start with auto-reload enabled for local development.
232+
233+
You can read more about it in the <a href="https://fastapi.tiangolo.com/fastapi-cli/" target="_blank">FastAPI CLI docs</a>.
233234

234235
</details>
235236

@@ -302,7 +303,7 @@ def update_item(item_id: int, item: Item):
302303
return {"item_name": item.name, "item_id": item_id}
303304
```
304305

305-
The server should reload automatically (because you added `--reload` to the `uvicorn` command above).
306+
The `fastapi dev` server should reload automatically.
306307

307308
### Interactive API docs upgrade
308309

@@ -446,7 +447,7 @@ Independent TechEmpower benchmarks show **FastAPI** applications running under U
446447

447448
To understand more about it, see the section <a href="https://fastapi.tiangolo.com/benchmarks/" class="internal-link" target="_blank">Benchmarks</a>.
448449

449-
## Optional Dependencies
450+
## Dependencies
450451

451452
Used by Pydantic:
452453

@@ -459,16 +460,33 @@ Used by Starlette:
459460
* <a href="https://www.python-httpx.org" target="_blank"><code>httpx</code></a> - Required if you want to use the `TestClient`.
460461
* <a href="https://jinja.palletsprojects.com" target="_blank"><code>jinja2</code></a> - Required if you want to use the default template configuration.
461462
* <a href="https://github.com/Kludex/python-multipart" target="_blank"><code>python-multipart</code></a> - Required if you want to support form <abbr title="converting the string that comes from an HTTP request into Python data">"parsing"</abbr>, with `request.form()`.
462-
* <a href="https://pythonhosted.org/itsdangerous/" target="_blank"><code>itsdangerous</code></a> - Required for `SessionMiddleware` support.
463-
* <a href="https://pyyaml.org/wiki/PyYAMLDocumentation" target="_blank"><code>pyyaml</code></a> - Required for Starlette's `SchemaGenerator` support (you probably don't need it with FastAPI).
464463

465464
Used by FastAPI / Starlette:
466465

467466
* <a href="https://www.uvicorn.org" target="_blank"><code>uvicorn</code></a> - for the server that loads and serves your application.
468467
* <a href="https://github.com/ijl/orjson" target="_blank"><code>orjson</code></a> - Required if you want to use `ORJSONResponse`.
469468
* <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - Required if you want to use `UJSONResponse`.
469+
* `fastapi-cli` - to provide the `fastapi` command.
470+
471+
When you install `fastapi` it comes these standard dependencies.
472+
473+
## `fastapi-slim`
474+
475+
If you don't want the extra standard optional dependencies, install `fastapi-slim` instead.
476+
477+
When you install with:
478+
479+
```bash
480+
pip install fastapi
481+
```
482+
483+
...it includes the same code and dependencies as:
484+
485+
```bash
486+
pip install "fastapi-slim[standard]"
487+
```
470488

471-
You can install all of these with `pip install "fastapi[all]"`.
489+
The standard extra dependencies are the ones mentioned above.
472490

473491
## License
474492

docs/en/docs/advanced/behind-a-proxy.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ Even though all your code is written assuming there's just `/app`.
2222
{!../../../docs_src/behind_a_proxy/tutorial001.py!}
2323
```
2424

25-
And the proxy would be **"stripping"** the **path prefix** on the fly before transmitting the request to Uvicorn, keeping your application convinced that it is being served at `/app`, so that you don't have to update all your code to include the prefix `/api/v1`.
25+
And the proxy would be **"stripping"** the **path prefix** on the fly before transmitting the request to the app server (probably Uvicorn via FastAPI CLI), keeping your application convinced that it is being served at `/app`, so that you don't have to update all your code to include the prefix `/api/v1`.
2626

2727
Up to here, everything would work as normally.
2828

@@ -63,7 +63,7 @@ The docs UI would also need the OpenAPI schema to declare that this API `server`
6363
}
6464
```
6565

66-
In this example, the "Proxy" could be something like **Traefik**. And the server would be something like **Uvicorn**, running your FastAPI application.
66+
In this example, the "Proxy" could be something like **Traefik**. And the server would be something like FastAPI CLI with **Uvicorn**, running your FastAPI application.
6767

6868
### Providing the `root_path`
6969

@@ -72,7 +72,7 @@ To achieve this, you can use the command line option `--root-path` like:
7272
<div class="termy">
7373

7474
```console
75-
$ uvicorn main:app --root-path /api/v1
75+
$ fastapi run main.py --root-path /api/v1
7676

7777
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
7878
```
@@ -101,7 +101,7 @@ Then, if you start Uvicorn with:
101101
<div class="termy">
102102

103103
```console
104-
$ uvicorn main:app --root-path /api/v1
104+
$ fastapi run main.py --root-path /api/v1
105105

106106
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
107107
```
@@ -216,12 +216,12 @@ INFO[0000] Configuration loaded from file: /home/user/awesomeapi/traefik.toml
216216

217217
</div>
218218

219-
And now start your app with Uvicorn, using the `--root-path` option:
219+
And now start your app, using the `--root-path` option:
220220

221221
<div class="termy">
222222

223223
```console
224-
$ uvicorn main:app --root-path /api/v1
224+
$ fastapi run main.py --root-path /api/v1
225225

226226
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
227227
```

docs/en/docs/advanced/openapi-callbacks.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ Now use the parameter `callbacks` in *your API's path operation decorator* to pa
172172

173173
### Check the docs
174174

175-
Now you can start your app with Uvicorn and go to <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
175+
Now you can start your app and go to <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
176176

177177
You will see your docs including a "Callbacks" section for your *path operation* that shows how the *external API* should look like:
178178

docs/en/docs/advanced/openapi-webhooks.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ This is because it is expected that **your users** would define the actual **URL
4444

4545
### Check the docs
4646

47-
Now you can start your app with Uvicorn and go to <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
47+
Now you can start your app and go to <a href="http://127.0.0.1:8000/docs" class="external-link" target="_blank">http://127.0.0.1:8000/docs</a>.
4848

4949
You will see your docs have the normal *path operations* and now also some **webhooks**:
5050

docs/en/docs/advanced/settings.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ Next, you would run the server passing the configurations as environment variabl
199199
<div class="termy">
200200

201201
```console
202-
$ ADMIN_EMAIL="[email protected]" APP_NAME="ChimichangApp" uvicorn main:app
202+
$ ADMIN_EMAIL="[email protected]" APP_NAME="ChimichangApp" fastapi run main.py
203203

204204
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
205205
```

docs/en/docs/advanced/websockets.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ If your file is named `main.py`, run your application with:
7272
<div class="termy">
7373

7474
```console
75-
$ uvicorn main:app --reload
75+
$ fastapi dev main.py
7676

7777
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
7878
```
@@ -160,7 +160,7 @@ If your file is named `main.py`, run your application with:
160160
<div class="termy">
161161

162162
```console
163-
$ uvicorn main:app --reload
163+
$ fastapi dev main.py
164164

165165
<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
166166
```

docs/en/docs/advanced/wsgi.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ Now, every request under the path `/v1/` will be handled by the Flask applicatio
2222

2323
And the rest will be handled by **FastAPI**.
2424

25-
If you run it with Uvicorn and go to <a href="http://localhost:8000/v1/" class="external-link" target="_blank">http://localhost:8000/v1/</a> you will see the response from Flask:
25+
If you run it and go to <a href="http://localhost:8000/v1/" class="external-link" target="_blank">http://localhost:8000/v1/</a> you will see the response from Flask:
2626

2727
```txt
2828
Hello, World from Flask!

docs/en/docs/css/termynal.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
position: relative;
2727
-webkit-box-sizing: border-box;
2828
box-sizing: border-box;
29+
line-height: 1.2;
2930
}
3031

3132
[data-termynal]:before {

docs/en/docs/deployment/concepts.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ In most cases, when you create a web API, you want it to be **always running**,
9494

9595
### In a Remote Server
9696

97-
When you set up a remote server (a cloud server, a virtual machine, etc.) the simplest thing you can do is to run Uvicorn (or similar) manually, the same way you do when developing locally.
97+
When you set up a remote server (a cloud server, a virtual machine, etc.) the simplest thing you can do is to use `fastapi run`, Uvicorn (or similar) manually, the same way you do when developing locally.
9898

9999
And it will work and will be useful **during development**.
100100

docs/en/docs/deployment/docker.md

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@ RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
2121

2222
COPY ./app /code/app
2323

24-
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]
24+
CMD ["fastapi", "run", "app/main.py", "--port", "80"]
2525

2626
# If running behind a proxy like Nginx or Traefik add --proxy-headers
27-
# CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80", "--proxy-headers"]
27+
# CMD ["fastapi", "run", "app/main.py", "--port", "80", "--proxy-headers"]
2828
```
2929

3030
</details>
@@ -113,9 +113,8 @@ You would of course use the same ideas you read in [About FastAPI versions](vers
113113
For example, your `requirements.txt` could look like:
114114

115115
```
116-
fastapi>=0.68.0,<0.69.0
117-
pydantic>=1.8.0,<2.0.0
118-
uvicorn>=0.15.0,<0.16.0
116+
fastapi>=0.112.0,<0.113.0
117+
pydantic>=2.7.0,<3.0.0
119118
```
120119

121120
And you would normally install those package dependencies with `pip`, for example:
@@ -125,16 +124,14 @@ And you would normally install those package dependencies with `pip`, for exampl
125124
```console
126125
$ pip install -r requirements.txt
127126
---> 100%
128-
Successfully installed fastapi pydantic uvicorn
127+
Successfully installed fastapi pydantic
129128
```
130129

131130
</div>
132131

133132
!!! info
134133
There are other formats and tools to define and install package dependencies.
135134

136-
I'll show you an example using Poetry later in a section below. 👇
137-
138135
### Create the **FastAPI** Code
139136

140137
* Create an `app` directory and enter it.
@@ -180,7 +177,7 @@ RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
180177
COPY ./app /code/app
181178

182179
# (6)
183-
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]
180+
CMD ["fastapi", "run", "app/main.py", "--port", "80"]
184181
```
185182

186183
1. Start from the official Python base image.
@@ -214,14 +211,12 @@ CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]
214211

215212
So, it's important to put this **near the end** of the `Dockerfile`, to optimize the container image build times.
216213

217-
6. Set the **command** to run the `uvicorn` server.
214+
6. Set the **command** to use `fastapi run`, which uses Uvicorn underneath.
218215

219216
`CMD` takes a list of strings, each of these strings is what you would type in the command line separated by spaces.
220217

221218
This command will be run from the **current working directory**, the same `/code` directory you set above with `WORKDIR /code`.
222219

223-
Because the program will be started at `/code` and inside of it is the directory `./app` with your code, **Uvicorn** will be able to see and **import** `app` from `app.main`.
224-
225220
!!! tip
226221
Review what each line does by clicking each number bubble in the code. 👆
227222

@@ -238,10 +233,10 @@ You should now have a directory structure like:
238233

239234
#### Behind a TLS Termination Proxy
240235

241-
If you are running your container behind a TLS Termination Proxy (load balancer) like Nginx or Traefik, add the option `--proxy-headers`, this will tell Uvicorn to trust the headers sent by that proxy telling it that the application is running behind HTTPS, etc.
236+
If you are running your container behind a TLS Termination Proxy (load balancer) like Nginx or Traefik, add the option `--proxy-headers`, this will tell Uvicorn (through the FastAPI CLI) to trust the headers sent by that proxy telling it that the application is running behind HTTPS, etc.
242237

243238
```Dockerfile
244-
CMD ["uvicorn", "app.main:app", "--proxy-headers", "--host", "0.0.0.0", "--port", "80"]
239+
CMD ["fastapi", "run", "app/main.py", "--proxy-headers", "--port", "80"]
245240
```
246241

247242
#### Docker Cache
@@ -362,14 +357,14 @@ RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
362357
COPY ./main.py /code/
363358

364359
# (2)
365-
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "80"]
360+
CMD ["fastapi", "run", "main.py", "--port", "80"]
366361
```
367362

368363
1. Copy the `main.py` file to the `/code` directory directly (without any `./app` directory).
369364

370-
2. Run Uvicorn and tell it to import the `app` object from `main` (instead of importing from `app.main`).
365+
2. Use `fastapi run` to serve your application in the single file `main.py`.
371366

372-
Then adjust the Uvicorn command to use the new module `main` instead of `app.main` to import the FastAPI object `app`.
367+
When you pass the file to `fastapi run` it will detect automatically that it is a single file and not part of a package and will know how to import it and serve your FastAPI app. 😎
373368

374369
## Deployment Concepts
375370

@@ -626,7 +621,7 @@ RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt
626621
COPY ./app /code/app
627622

628623
# (11)
629-
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]
624+
CMD ["fastapi", "run", "app/main.py", "--port", "80"]
630625
```
631626

632627
1. This is the first stage, it is named `requirements-stage`.
@@ -655,7 +650,7 @@ CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]
655650

656651
10. Copy the `app` directory to the `/code` directory.
657652

658-
11. Run the `uvicorn` command, telling it to use the `app` object imported from `app.main`.
653+
11. Use the `fastapi run` command to run your app.
659654

660655
!!! tip
661656
Click the bubble numbers to see what each line does.
@@ -677,7 +672,7 @@ Then in the next (and final) stage you would build the image more or less in the
677672
Again, if you are running your container behind a TLS Termination Proxy (load balancer) like Nginx or Traefik, add the option `--proxy-headers` to the command:
678673

679674
```Dockerfile
680-
CMD ["uvicorn", "app.main:app", "--proxy-headers", "--host", "0.0.0.0", "--port", "80"]
675+
CMD ["fastapi", "run", "app/main.py", "--proxy-headers", "--port", "80"]
681676
```
682677

683678
## Recap

0 commit comments

Comments
 (0)