Skip to content

Commit

Permalink
✨ Add FastAPI CLI, the new fastapi command (#11522)
Browse files Browse the repository at this point in the history
  • Loading branch information
tiangolo authored May 2, 2024
1 parent a94ef33 commit d71be59
Show file tree
Hide file tree
Showing 18 changed files with 376 additions and 165 deletions.
70 changes: 44 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,18 +139,6 @@ $ pip install fastapi

</div>

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>.

<div class="termy">

```console
$ pip install "uvicorn[standard]"

---> 100%
```

</div>

## Example

### Create it
Expand Down Expand Up @@ -211,25 +199,38 @@ Run the server with:
<div class="termy">

```console
$ uvicorn main:app --reload

$ fastapi dev main.py

╭────────── FastAPI CLI - Development mode ───────────╮
│ │
│ Serving at: http://127.0.0.1:8000 │
│ │
│ API docs: http://127.0.0.1:8000/docs │
│ │
│ Running in development mode, for production use: │
│ │
│ fastapi run │
│ │
╰─────────────────────────────────────────────────────╯

INFO: Will watch for changes in these directories: ['/home/user/code/awesomeapp']
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO: Started reloader process [28720]
INFO: Started server process [28722]
INFO: Started reloader process [2248755] using WatchFiles
INFO: Started server process [2248757]
INFO: Waiting for application startup.
INFO: Application startup complete.
```

</div>

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

The command `uvicorn main:app` refers to:
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>.

* `main`: the file `main.py` (the Python "module").
* `app`: the object created inside of `main.py` with the line `app = FastAPI()`.
* `--reload`: make the server restart after code changes. Only do this for development.
By default, `fastapi dev` will start with auto-reload enabled for local development.

You can read more about it in the <a href="https://fastapi.tiangolo.com/fastapi-cli/" target="_blank">FastAPI CLI docs</a>.

</details>

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

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

### Interactive API docs upgrade

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

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

## Optional Dependencies
## Dependencies

Used by Pydantic:

Expand All @@ -459,16 +460,33 @@ Used by Starlette:
* <a href="https://www.python-httpx.org" target="_blank"><code>httpx</code></a> - Required if you want to use the `TestClient`.
* <a href="https://jinja.palletsprojects.com" target="_blank"><code>jinja2</code></a> - Required if you want to use the default template configuration.
* <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()`.
* <a href="https://pythonhosted.org/itsdangerous/" target="_blank"><code>itsdangerous</code></a> - Required for `SessionMiddleware` support.
* <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).

Used by FastAPI / Starlette:

* <a href="https://www.uvicorn.org" target="_blank"><code>uvicorn</code></a> - for the server that loads and serves your application.
* <a href="https://github.com/ijl/orjson" target="_blank"><code>orjson</code></a> - Required if you want to use `ORJSONResponse`.
* <a href="https://github.com/esnme/ultrajson" target="_blank"><code>ujson</code></a> - Required if you want to use `UJSONResponse`.
* `fastapi-cli` - to provide the `fastapi` command.

When you install `fastapi` it comes these standard dependencies.

## `fastapi-slim`

If you don't want the extra standard optional dependencies, install `fastapi-slim` instead.

When you install with:

```bash
pip install fastapi
```

...it includes the same code and dependencies as:

```bash
pip install "fastapi-slim[standard]"
```

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

## License

Expand Down
12 changes: 6 additions & 6 deletions docs/en/docs/advanced/behind-a-proxy.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Even though all your code is written assuming there's just `/app`.
{!../../../docs_src/behind_a_proxy/tutorial001.py!}
```

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`.
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`.

Up to here, everything would work as normally.

Expand Down Expand Up @@ -63,7 +63,7 @@ The docs UI would also need the OpenAPI schema to declare that this API `server`
}
```

In this example, the "Proxy" could be something like **Traefik**. And the server would be something like **Uvicorn**, running your FastAPI application.
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.

### Providing the `root_path`

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

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

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

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

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

</div>

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

<div class="termy">

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

<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
Expand Down
2 changes: 1 addition & 1 deletion docs/en/docs/advanced/openapi-callbacks.md
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ Now use the parameter `callbacks` in *your API's path operation decorator* to pa

### Check the docs

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>.
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>.

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

Expand Down
2 changes: 1 addition & 1 deletion docs/en/docs/advanced/openapi-webhooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ This is because it is expected that **your users** would define the actual **URL

### Check the docs

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>.
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>.

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

Expand Down
2 changes: 1 addition & 1 deletion docs/en/docs/advanced/settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ Next, you would run the server passing the configurations as environment variabl
<div class="termy">

```console
$ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" uvicorn main:app
$ ADMIN_EMAIL="deadpool@example.com" APP_NAME="ChimichangApp" fastapi run main.py

<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
Expand Down
4 changes: 2 additions & 2 deletions docs/en/docs/advanced/websockets.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ If your file is named `main.py`, run your application with:
<div class="termy">

```console
$ uvicorn main:app --reload
$ fastapi dev main.py

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

```console
$ uvicorn main:app --reload
$ fastapi dev main.py

<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
```
Expand Down
2 changes: 1 addition & 1 deletion docs/en/docs/advanced/wsgi.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Now, every request under the path `/v1/` will be handled by the Flask applicatio

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

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:
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:

```txt
Hello, World from Flask!
Expand Down
1 change: 1 addition & 0 deletions docs/en/docs/css/termynal.css
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
position: relative;
-webkit-box-sizing: border-box;
box-sizing: border-box;
line-height: 1.2;
}

[data-termynal]:before {
Expand Down
2 changes: 1 addition & 1 deletion docs/en/docs/deployment/concepts.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ In most cases, when you create a web API, you want it to be **always running**,

### In a Remote Server

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.
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.

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

Expand Down
35 changes: 15 additions & 20 deletions docs/en/docs/deployment/docker.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt

COPY ./app /code/app

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

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

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

```
fastapi>=0.68.0,<0.69.0
pydantic>=1.8.0,<2.0.0
uvicorn>=0.15.0,<0.16.0
fastapi>=0.112.0,<0.113.0
pydantic>=2.7.0,<3.0.0
```

And you would normally install those package dependencies with `pip`, for example:
Expand All @@ -125,16 +124,14 @@ And you would normally install those package dependencies with `pip`, for exampl
```console
$ pip install -r requirements.txt
---> 100%
Successfully installed fastapi pydantic uvicorn
Successfully installed fastapi pydantic
```

</div>

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

I'll show you an example using Poetry later in a section below. 👇

### Create the **FastAPI** Code

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

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

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

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

6. Set the **command** to run the `uvicorn` server.
6. Set the **command** to use `fastapi run`, which uses Uvicorn underneath.

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

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

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`.

!!! tip
Review what each line does by clicking each number bubble in the code. 👆

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

#### Behind a TLS Termination Proxy

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.
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.

```Dockerfile
CMD ["uvicorn", "app.main:app", "--proxy-headers", "--host", "0.0.0.0", "--port", "80"]
CMD ["fastapi", "run", "app/main.py", "--proxy-headers", "--port", "80"]
```

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

# (2)
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "80"]
CMD ["fastapi", "run", "main.py", "--port", "80"]
```

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

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

Then adjust the Uvicorn command to use the new module `main` instead of `app.main` to import the FastAPI object `app`.
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. 😎

## Deployment Concepts

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

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

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

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

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

!!! tip
Click the bubble numbers to see what each line does.
Expand All @@ -677,7 +672,7 @@ Then in the next (and final) stage you would build the image more or less in the
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:

```Dockerfile
CMD ["uvicorn", "app.main:app", "--proxy-headers", "--host", "0.0.0.0", "--port", "80"]
CMD ["fastapi", "run", "app/main.py", "--proxy-headers", "--port", "80"]
```

## Recap
Expand Down
Loading

0 comments on commit d71be59

Please sign in to comment.