<ahref="https://www.coderabbit.ai/?utm_source=fastapi&utm_medium=badge&utm_campaign=fastapi"target="_blank"title="Cut Code Review Time & Bugs in Half with CodeRabbit"><imgsrc="https://fastapi.tiangolo.com/img/sponsors/coderabbit.png"></a>
<ahref="https://subtotal.com/?utm_source=fastapi&utm_medium=sponsorship&utm_campaign=open-source"target="_blank"title="The Gold Standard in Retail Account Linking"><imgsrc="https://fastapi.tiangolo.com/img/sponsors/subtotal.svg"></a>
<ahref="https://vibe.mobb.ai/?utm_source=Fast+APi&utm_medium=Image&utm_campaign=MVS"target="_blank"title="Secure Your AI-Generated Code to Unlock Dev Productivity"><imgsrc="https://fastapi.tiangolo.com/img/sponsors/mobbai.png"></a>
<ahref="https://databento.com/"target="_blank"title="Pay as you go for market data"><imgsrc="https://fastapi.tiangolo.com/img/sponsors/databento.svg"></a>
<ahref="https://docs.railway.com/guides/fastapi?utm_medium=integration&utm_source=docs&utm_campaign=fastapi"target="_blank"title="Deploy enterprise applications at startup speed"><imgsrc="https://fastapi.tiangolo.com/img/sponsors/railway.png"></a>
<ahref="https://databento.com/?utm_source=fastapi&utm_medium=sponsor&utm_content=display"target="_blank"title="Pay as you go for market data"><imgsrc="https://fastapi.tiangolo.com/img/sponsors/databento.svg"></a>
<ahref="https://speakeasy.com/editor?utm_source=fastapi+repo&utm_medium=github+sponsorship"target="_blank"title="SDKs for your API | Speakeasy"><imgsrc="https://fastapi.tiangolo.com/img/sponsors/speakeasy.png"></a>
<ahref="https://www.svix.com/"target="_blank"title="Svix - Webhooks as a service"><imgsrc="https://fastapi.tiangolo.com/img/sponsors/svix.svg"></a>
As **FastAPI** is based on the OpenAPI specification, you get automatic compatibility with many tools, including the automatic API docs (provided by Swagger UI).
Because **FastAPI** is based on the **OpenAPI** specification, its APIs can be described in a standard format that many tools understand.
One particular advantage that is not necessarily obvious is that you can **generate clients** (sometimes called <abbrtitle="Software Development Kits">**SDKs**</abbr> ) for your API, for many different **programming languages**.
This makes it easy to generate up-to-date **documentation**, client libraries (<abbrtitle="Software Development Kits">**SDKs**</abbr>) in multiple languages, and **testing** or **automation workflows** that stay in sync with your code.
## OpenAPI Client Generators
In this guide, you'll learn how to generate a **TypeScript SDK** for your FastAPI backend.
There are many tools to generate clients from **OpenAPI**.
## Open Source SDK Generators
A common tool is<ahref="https://openapi-generator.tech/"class="external-link"target="_blank">OpenAPI Generator</a>.
A versatile option is the<ahref="https://openapi-generator.tech/"class="external-link"target="_blank">OpenAPI Generator</a>, which supports **many programming languages** and can generate SDKs from your OpenAPI specification.
If you are building a **frontend**, a very interesting alternative is<ahref="https://github.com/hey-api/openapi-ts"class="external-link"target="_blank">openapi-ts</a>.
For **TypeScript clients**,<ahref="https://heyapi.dev/"class="external-link"target="_blank">Hey API</a> is a purpose-built solution, providing an optimized experience for the TypeScript ecosystem.
## Client and SDK Generators - Sponsor
You can discover more SDK generators on <ahref="https://openapi.tools/#sdk"class="external-link"target="_blank">OpenAPI.Tools</a>.
There are also some **company-backed** Client and SDK generators based on OpenAPI (FastAPI), in some cases they can offer you **additional features** on top of high-quality generated SDKs/clients.
/// tip
FastAPI automatically generates **OpenAPI 3.1** specifications, so any tool you use must support this version.
///
## SDK Generators from FastAPI Sponsors
This section highlights **venture-backed** and **company-supported** solutions from companies that sponsor FastAPI. These products provide **additional features** and **integrations** on top of high-quality generated SDKs.
Some of them also ✨ [**sponsor FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} ✨, this ensures the continued and healthy **development** of FastAPI and its **ecosystem**.
By ✨ [**sponsoring FastAPI**](../help-fastapi.md#sponsor-the-author){.internal-link target=_blank} ✨, these companies help ensure the framework and its **ecosystem** remain healthy and **sustainable**.
And it shows their true commitment to FastAPI and its **community** (you), as they not only want to provide you a **good service** but also want to make sure you have a **good and healthy framework**, FastAPI. 🙇
Their sponsorship also demonstrates a strong commitment to the FastAPI **community** (you), showing that they care not only about offering a **great service** but also about supporting a **robust and thriving framework**, FastAPI. 🙇
There are also several other companies offering similar services that you can search and find online. 🤓
Some of these solutions may also be open source or offer free tiers, so you can try them without a financial commitment. Other commercial SDK generators are available and can be found online. 🤓
## Generate a TypeScript Frontend Client
## Create a TypeScript SDK
Let's start with a simple FastAPI application:
@ -38,78 +46,31 @@ Notice that the *path operations* define the models they use for request payload
### API Docs
If you go to the API docs, you will see that it has the **schemas** for the data to be sent in requests and received in responses:
If you go to `/docs`, you will see that it has the **schemas** for the data to be sent in requests and received in responses:
This will generate a TypeScript SDK in `./src/client`.
To generate the client code you can use the command line application `openapi-ts` that would now be installed.
You can learn how to <ahref="https://heyapi.dev/openapi-ts/get-started"class="external-link"target="_blank">install `@hey-api/openapi-ts`</a> and read about the <ahref="https://heyapi.dev/openapi-ts/output"class="external-link"target="_blank">generated output</a> on their website.
Because it is installed in the local project, you probably wouldn't be able to call that command directly, but you would put it on your `package.json` file.
@ -170,13 +131,13 @@ But I'll show you how to improve that next. 🤓
You can **modify** the way these operation IDs are **generated** to make them simpler and have **simpler method names** in the clients.
In this case you will have to ensure that each operation ID is **unique** in some other way.
In this case, you will have to ensure that each operation ID is **unique** in some other way.
For example, you could make sure that each *path operation* has a tag, and then generate the operation ID based on the **tag** and the *path operation***name** (the function name).
### Custom Generate Unique ID Function
FastAPI uses a **unique ID** for each *path operation*, it is used for the **operation ID** and also for the names of any needed custom models, for requests or responses.
FastAPI uses a **unique ID** for each *path operation*, which is used for the **operation ID** and also for the names of any needed custom models, for requests or responses.
You can customize that function. It takes an `APIRoute` and outputs a string.
@ -188,7 +149,7 @@ You can then pass that custom function to **FastAPI** as the `generate_unique_id
### Generate a TypeScript Client with Custom Operation IDs
Now if you generate the client again, you will see that it has the improved method names:
Now, if you generate the client again, you will see that it has the improved method names:
@ -202,7 +163,7 @@ We already know that this method is related to the **items** because that word i
We will probably still want to keep it for OpenAPI in general, as that will ensure that the operation IDs are **unique**.
But for the generated client we could **modify** the OpenAPI operation IDs right before generating the clients, just to make those method names nicer and **cleaner**.
But for the generated client, we could **modify** the OpenAPI operation IDs right before generating the clients, just to make those method names nicer and **cleaner**.
We could download the OpenAPI JSON to a file `openapi.json` and then we could **remove that prefixed tag** with a script like this:
@ -220,24 +181,10 @@ With that, the operation IDs would be renamed from things like `items-get_items`
### Generate a TypeScript Client with the Preprocessed OpenAPI
Now as the end result is in a file `openapi.json`, you would modify the `package.json` to use that local file, for example:
After generating the new client, you would now have **clean method names**, with all the **autocompletion**, **inline errors**, etc:
@ -246,7 +193,7 @@ After generating the new client, you would now have **clean method names**, with
## Benefits
When using the automatically generated clients you would get **autocompletion** for:
When using the automatically generated clients, you would get **autocompletion** for:
* Methods.
* Request payloads in the body, query parameters, etc.
@ -256,6 +203,6 @@ You would also have **inline errors** for everything.
And whenever you update the backend code, and **regenerate** the frontend, it would have any new *path operations* available as methods, the old ones removed, and any other change would be reflected on the generated code. 🤓
This also means that if something changed it will be **reflected** on the client code automatically. And if you **build** the client it will error out if you have any **mismatch** in the data used.
This also means that if something changed, it will be **reflected** on the client code automatically. And if you **build** the client, it will error out if you have any **mismatch** in the data used.
So, you would **detect many errors** very early in the development cycle instead of having to wait for the errors to show up to your final users in production and then trying to debug where the problem is. ✨
@ -315,30 +315,47 @@ Now you can translate it all and see how it looks as you save the file.
Some of these files are updated very frequently and a translation would always be behind, or they include the main content from English source files, etc.
#### Request a New Language
Let's say that you want to request translations for a language that is not yet translated, not even some pages. For example, Latin.
If there is no discussion for that language, you can start by requesting the new language. For that, you can follow these steps:
* Create a new discussion following the template.
* Get a few native speakers to comment on the discussion and commit to help review translations for that language.
Once there are several people in the discussion, the FastAPI team can evaluate it and can make it an official translation.
Then the docs will be automatically translated using AI, and the team of native speakers can review the translation, and help tweak the AI prompts.
Once there's a new translation, for example if docs are updated or there's a new section, there will be a comment in the same discussion with the link to the new translation to review.
#### New Language
Let's say that you want to add translations for a language that is not yet translated, not even some pages.
/// note
Let's say you want to add translations for Creole, and it's not yet there in the docs.
These steps will be performed by the FastAPI team.
///
Checking the link from above, the code for "Creole" is `ht`.
Checking the link from above (List of ISO 639-1 codes), you can see that the 2-letter code for Latin is `la`.
The next step is to run the script to generate a new translation directory:
Now you can create a new directory for the new language, running the following script:
<divclass="termy">
```console
// Use the command new-lang, pass the language code as a CLI argument
$ python ./scripts/docs.py new-lang ht
$ python ./scripts/docs.py new-lang la
Successfully initialized: docs/ht
Successfully initialized: docs/la
```
</div>
Now you can check in your code editor the newly created directory `docs/ht/`.
Now you can check in your code editor the newly created directory `docs/la/`.
That command created a file `docs/ht/mkdocs.yml` with a simple config that inherits everything from the `en` version:
That command created a file `docs/la/mkdocs.yml` with a simple config that inherits everything from the `en` version:
```yaml
INHERIT: ../en/mkdocs.yml
@ -350,11 +367,11 @@ You could also simply create that file with those contents manually.
///
That command also created a dummy file `docs/ht/index.md` for the main page, you can start by translating that one.
That command also created a dummy file `docs/la/index.md` for the main page, you can start by translating that one.
You can continue with the previous instructions for an "Existing Language" for that process.
You can make the first pull request with those two files, `docs/ht/mkdocs.yml` and `docs/ht/index.md`. 🎉
You can make the first pull request with those two files, `docs/la/mkdocs.yml` and `docs/la/index.md`. 🎉
* 📝 Update `docs/en/docs/advanced/generate-clients.md`. PR [#13793](https://github.com/fastapi/fastapi/pull/13793) by [@mrlubos](https://github.com/mrlubos).
* 📝 Add discussion template for new language translation requests. PR [#13535](https://github.com/fastapi/fastapi/pull/13535) by [@alejsdev](https://github.com/alejsdev).
### Translations
* 🌐 Update Portuguese Translation for `docs/pt/docs/async.md`. PR [#13863](https://github.com/fastapi/fastapi/pull/13863) by [@EdmilsonRodrigues](https://github.com/EdmilsonRodrigues).
* 📝 Fix highlight line in `docs/ja/docs/tutorial/body.md`. PR [#13927](https://github.com/fastapi/fastapi/pull/13927) by [@KoyoMiyazaki](https://github.com/KoyoMiyazaki).
* 🌐 Add Persian translation for `docs/fa/docs/environment-variables.md`. PR [#13923](https://github.com/fastapi/fastapi/pull/13923) by [@Mohammad222PR](https://github.com/Mohammad222PR).
* 🌐 Add Persian translation for `docs/fa/docs/python-types.md`. PR [#13524](https://github.com/fastapi/fastapi/pull/13524) by [@Mohammad222PR](https://github.com/Mohammad222PR).
* 🌐 Update Portuguese Translation for `docs/pt/docs/project-generation.md`. PR [#13875](https://github.com/fastapi/fastapi/pull/13875) by [@EdmilsonRodrigues](https://github.com/EdmilsonRodrigues).
* 🌐 Add Persian translation for `docs/fa/docs/async.md`. PR [#13541](https://github.com/fastapi/fastapi/pull/13541) by [@Mohammad222PR](https://github.com/Mohammad222PR).
@ -16,6 +24,31 @@ hide:
### Internal
* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13983](https://github.com/fastapi/fastapi/pull/13983) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci).
* ⬆ Bump actions/checkout from 4 to 5. PR [#13986](https://github.com/fastapi/fastapi/pull/13986) by [@dependabot[bot]](https://github.com/apps/dependabot).
* 🔧 Update Speakeasy sponsor graphic. PR [#13971](https://github.com/fastapi/fastapi/pull/13971) by [@chailandau](https://github.com/chailandau).
* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13969](https://github.com/fastapi/fastapi/pull/13969) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci).
* ⬆ Bump actions/download-artifact from 4 to 5. PR [#13975](https://github.com/fastapi/fastapi/pull/13975) by [@dependabot[bot]](https://github.com/apps/dependabot).
* 👥 Update FastAPI People - Experts. PR [#13963](https://github.com/fastapi/fastapi/pull/13963) by [@tiangolo](https://github.com/tiangolo).
* ⬆ Bump ruff from 0.11.2 to 0.12.7. PR [#13957](https://github.com/fastapi/fastapi/pull/13957) by [@dependabot[bot]](https://github.com/apps/dependabot).
* ⬆ Bump cairosvg from 2.7.1 to 2.8.2. PR [#13959](https://github.com/fastapi/fastapi/pull/13959) by [@dependabot[bot]](https://github.com/apps/dependabot).
* ⬆ Bump pydantic-ai from 0.0.30 to 0.4.10. PR [#13958](https://github.com/fastapi/fastapi/pull/13958) by [@dependabot[bot]](https://github.com/apps/dependabot).
* ⬆ Bump mkdocs-material from 9.6.15 to 9.6.16. PR [#13961](https://github.com/fastapi/fastapi/pull/13961) by [@dependabot[bot]](https://github.com/apps/dependabot).
* ⬆ Bump tiangolo/latest-changes from 0.3.2 to 0.4.0. PR [#13952](https://github.com/fastapi/fastapi/pull/13952) by [@dependabot[bot]](https://github.com/apps/dependabot).
* 👥 Update FastAPI People - Sponsors. PR [#13956](https://github.com/fastapi/fastapi/pull/13956) by [@tiangolo](https://github.com/tiangolo).
* 👥 Update FastAPI People - Contributors and Translators. PR [#13955](https://github.com/fastapi/fastapi/pull/13955) by [@tiangolo](https://github.com/tiangolo).
* 🔧 Update sponsors: Databento link and sponsors_badge data. PR [#13954](https://github.com/fastapi/fastapi/pull/13954) by [@tiangolo](https://github.com/tiangolo).
* 🔧 Update sponsors: Add Railway. PR [#13953](https://github.com/fastapi/fastapi/pull/13953) by [@tiangolo](https://github.com/tiangolo).
* ⚒️ Update translate script, update prompt to minimize generated diff. PR [#13947](https://github.com/fastapi/fastapi/pull/13947) by [@YuriiMotov](https://github.com/YuriiMotov).
* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13943](https://github.com/fastapi/fastapi/pull/13943) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci).
* ⚒️ Tweak translate script and CI. PR [#13939](https://github.com/fastapi/fastapi/pull/13939) by [@tiangolo](https://github.com/tiangolo).
* 👷 Add CI to translate with LLMs. PR [#13937](https://github.com/fastapi/fastapi/pull/13937) by [@tiangolo](https://github.com/tiangolo).
* ⚒️ Update translate script, show and update outdated translations. PR [#13933](https://github.com/fastapi/fastapi/pull/13933) by [@tiangolo](https://github.com/tiangolo).
* 🔨 Refactor translate script with extra feedback (prints). PR [#13932](https://github.com/fastapi/fastapi/pull/13932) by [@tiangolo](https://github.com/tiangolo).
* 🔨 Update translations script to remove old (removed) files. PR [#13928](https://github.com/fastapi/fastapi/pull/13928) by [@tiangolo](https://github.com/tiangolo).
* ⬆ [pre-commit.ci] pre-commit autoupdate. PR [#13894](https://github.com/fastapi/fastapi/pull/13894) by [@pre-commit-ci[bot]](https://github.com/apps/pre-commit-ci).
* ⬆ Update httpx requirement to >=0.23.0,<0.29.0.PR [#13114](https://github.com/fastapi/fastapi/pull/13114) by [@yan12125](https://github.com/yan12125).
* 🔧 Update sponsors: Add Mobb. PR [#13916](https://github.com/fastapi/fastapi/pull/13916) by [@tiangolo](https://github.com/tiangolo).
* 👥 Update FastAPI People - Experts. PR [#13889](https://github.com/fastapi/fastapi/pull/13889) by [@tiangolo](https://github.com/tiangolo).
* 🔨 Update FastAPI People sleep interval, use external settings. PR [#13888](https://github.com/fastapi/fastapi/pull/13888) by [@tiangolo](https://github.com/tiangolo).
اگه از قبل میدونی متغیرهای محیطی چی هستن و چطور ازشون استفاده میشه، میتونی این بخش رو رد کنی.
///
یه متغیر محیطی (که بهش "**env var**" هم میگن) یه متغیریه که **خارج** از کد پایتون، توی **سیستمعامل** زندگی میکنه و میتونه توسط کد پایتونت (یا برنامههای دیگه) خونده بشه.
متغیرهای محیطی میتونن برای مدیریت **تنظیمات** برنامه، بهعنوان بخشی از **نصب** پایتون و غیره مفید باشن.
## ساخت و استفاده از متغیرهای محیطی
میتونی متغیرهای محیطی رو توی **شل (ترمینال)****بسازی** و ازشون استفاده کنی، بدون اینکه به پایتون نیاز داشته باشی:
//// tab | لینوکس، مکاواس، ویندوز بش
<divclass="termy">
```console
// میتونی یه متغیر محیطی به اسم MY_NAME بسازی با
$ export MY_NAME="Wade Wilson"
// بعد میتونی با برنامههای دیگه ازش استفاده کنی، مثل
$ echo "Hello $MY_NAME"
Hello Wade Wilson
```
</div>
////
//// tab | ویندوز پاورشل
<divclass="termy">
```console
// یه متغیر محیطی به اسم MY_NAME بساز
$ $Env:MY_NAME = "Wade Wilson"
// با برنامههای دیگه ازش استفاده کن، مثل
$ echo "Hello $Env:MY_NAME"
Hello Wade Wilson
```
</div>
////
## خوندن متغیرهای محیطی توی پایتون
میتونی متغیرهای محیطی رو **خارج** از پایتون، توی ترمینال (یا با هر روش دیگه) بسازی، و بعد توی **پایتون** اونا رو بخونی.
مثلاً میتونی یه فایل `main.py` داشته باشی با:
```Python hl_lines="3"
import os
name = os.getenv("MY_NAME", "World")
print(f"Hello {name} from Python")
```
/// tip
آرگومان دوم <ahref="https://docs.python.org/3.8/library/os.html#os.getenv"class="external-link"target="_blank">`os.getenv()`</a> مقدار پیشفرضیه که برمیگردونه.
اگه ندی، بهصورت پیشفرض `None` هست، اینجا ما `"World"` رو بهعنوان مقدار پیشفرض گذاشتیم.
///
بعد میتونی اون برنامه پایتون رو صدا کنی:
//// tab | لینوکس، مکاواس، ویندوز بش
<divclass="termy">
```console
// اینجا هنوز متغیر محیطی رو تنظیم نکردیم
$ python main.py
// چون متغیر محیطی رو تنظیم نکردیم، مقدار پیشفرض رو میگیریم
Hello World from Python
// ولی اگه اول یه متغیر محیطی بسازیم
$ export MY_NAME="Wade Wilson"
// و بعد دوباره برنامه رو صدا کنیم
$ python main.py
// حالا میتونه متغیر محیطی رو بخونه
Hello Wade Wilson from Python
```
</div>
////
//// tab | ویندوز پاورشل
<divclass="termy">
```console
// اینجا هنوز متغیر محیطی رو تنظیم نکردیم
$ python main.py
// چون متغیر محیطی رو تنظیم نکردیم، مقدار پیشفرض رو میگیریم
Hello World from Python
// ولی اگه اول یه متغیر محیطی بسازیم
$ $Env:MY_NAME = "Wade Wilson"
// و بعد دوباره برنامه رو صدا کنیم
$ python main.py
// حالا میتونه متغیر محیطی رو بخونه
Hello Wade Wilson from Python
```
</div>
////
چون متغیرهای محیطی میتونن خارج از کد تنظیم بشن، ولی کد میتونه اونا رو بخونه، و لازم نیست با بقیه فایلها ذخیره (کمیتی به `git`) بشن، معمولاً برای پیکربندی یا **تنظیمات** استفاده میشن.
همچنین میتونی یه متغیر محیطی رو فقط برای **یه اجرای خاص برنامه** بسازی، که فقط برای اون برنامه و فقط برای مدت زمان اجراش در دسترسه.
برای این کار، درست قبل از خود برنامه، توی همون خط بسازش:
<divclass="termy">
```console
// یه متغیر محیطی MY_NAME رو توی خط برای این اجرای برنامه بساز
$ MY_NAME="Wade Wilson" python main.py
// حالا میتونه متغیر محیطی رو بخونه
Hello Wade Wilson from Python
// متغیر محیطی بعدش دیگه وجود نداره
$ python main.py
Hello World from Python
```
</div>
/// tip
میتونی بیشتر در موردش توی <ahref="https://12factor.net/config"class="external-link"target="_blank">برنامه دوازدهفاکتوری: پیکربندی</a> بخونی.
///
## نوعها و اعتبارسنجی
این متغیرهای محیطی فقط میتونن **رشتههای متنی** رو نگه دارن، چون خارج از پایتون هستن و باید با برنامههای دیگه و بقیه سیستم (و حتی سیستمعاملهای مختلف مثل لینوکس، ویندوز، مکاواس) سازگار باشن.
یعنی **هر مقداری** که توی پایتون از یه متغیر محیطی خونده میشه یه `str` هست، و هر تبدیل به نوع دیگه یا هر اعتبارسنجی باید توی کد انجام بشه.
توی [راهنمای کاربر پیشرفته - تنظیمات و متغیرهای محیطی](./advanced/settings.md){.internal-link target=_blank} بیشتر در مورد استفاده از متغیرهای محیطی برای مدیریت **تنظیمات برنامه** یاد میگیری.
## متغیر محیطی `PATH`
یه متغیر محیطی **خاص** به اسم **`PATH`** وجود داره که سیستمعاملها (لینوکس، مکاواس، ویندوز) ازش برای پیدا کردن برنامههایی که قراره اجرا بشن استفاده میکنن.
مقدار متغیر `PATH` یه رشته طولانی از پوشههاست که توی لینوکس و مکاواس با دونقطه `:` و توی ویندوز با نقطهویرگول `;` از هم جدا شدن.
مثلاً، متغیر محیطی `PATH` میتونه اینجوری باشه:
//// tab | لینوکس، مکاواس
```plaintext
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
```
یعنی سیستم باید دنبال برنامهها توی این پوشهها بگرده:
اینجوری، وقتی توی ترمینال `python` تایپ میکنی، سیستم برنامه پایتون رو توی `C:\opt\custompython\bin` (آخرین پوشه) پیدا میکنه و از اون استفاده میکنه.
////
پس، اگه تایپ کنی:
<divclass="termy">
```console
$ python
```
</div>
//// tab | لینوکس، مکاواس
سیستم برنامه `python` رو توی `/opt/custompython/bin`**پیدا** میکنه و اجراش میکنه.
تقریباً معادل اینه که تایپ کنی:
<divclass="termy">
```console
$ /opt/custompython/bin/python
```
</div>
////
//// tab | ویندوز
سیستم برنامه `python` رو توی `C:\opt\custompython\bin\python`**پیدا** میکنه و اجراش میکنه.
تقریباً معادل اینه که تایپ کنی:
<divclass="termy">
```console
$ C:\opt\custompython\bin\python
```
</div>
////
این اطلاعات وقتی در مورد [محیطهای مجازی](virtual-environments.md){.internal-link target=_blank} یاد میگیری بهدردت میخوره.
## نتیجهگیری
با این باید یه درک پایهای از **متغیرهای محیطی** و نحوه استفادهشون توی پایتون داشته باشی.
میتونی بیشتر در موردشون توی <ahref="https://en.wikipedia.org/wiki/Environment_variable"class="external-link"target="_blank">ویکیپدیا برای متغیر محیطی</a> بخونی.
توی خیلی موارد مشخص نیست که متغیرهای محیطی چطور میتونن فوری مفید و کاربردی باشن. ولی توی موقعیتهای مختلف توسعه مدام پیداشون میشه، پس خوبه که در موردشون بدونی.
مثلاً، توی بخش بعدی در مورد [محیطهای مجازی](virtual-environments.md) به این اطلاعات نیاز داری.
Se sua aplicação (de alguma forma) não tem que se comunicar com nada mais e tem que esperar que o respondam, use `async def`.
Se sua aplicação (de alguma forma) não tem que se comunicar com nada mais e esperar que o respondam, use `async def`.
---
@ -52,7 +52,7 @@ Se você simplesmente não sabe, use apenas `def`.
De qualquer forma, em ambos os casos acima, FastAPI irá trabalhar assincronamente e ser extremamente rápido.
Seguindo os passos acima, ele será capaz de fazer algumas otimizações de performance.
Mas, seguindo os passos acima, ele será capaz de fazer algumas otimizações de performance.
## Detalhes Técnicos
@ -66,36 +66,36 @@ Vamos ver aquela frase por partes na seção abaixo:
## Código assíncrono
Código assíncrono apenas significa que a linguagem 💬 tem um jeito de dizer para o computador / programa 🤖 que em certo ponto, ele 🤖 terá que esperar por *algo* para finalizar em outro lugar. Vamos dizer que esse *algo* seja chamado "arquivo lento" 📝.
Código assíncrono apenas significa que a linguagem 💬 tem um jeito de dizer para o computador / programa 🤖 que em certo ponto do código, ele 🤖 terá que esperar *algo* finalizar em outro lugar. Vamos dizer que esse *algo* seja chamado "arquivo lento" 📝.
Então, durante esse tempo, o computador pode ir e fazer outro trabalho, enquanto o "arquivo lento" 📝 termine.
Então, durante esse tempo, o computador pode ir e fazer outro trabalho, enquanto o "arquivo lento" 📝 termina.
Então o computador / programa 🤖 irá voltar toda hora que tiver uma chance porquê ele ainda está esperando o "arquivo lento", ou ele 🤖 nunca irá terminar todo o trabalho que tem até esse ponto. E ele 🤖 irá ver se alguma das tarefas que estava esperando já terminaram, fazendo o que quer que tinham que fazer.
Então o computador / programa 🤖 irá voltar sempre que tiver uma chance, seja porque ele está esperando novamente, ou quando ele 🤖 terminar todo o trabalho que tem até esse ponto. E ele 🤖 irá ver se alguma das tarefas que estava esperando já terminaram de fazer o que quer que tinham que fazer.
Depois, ele 🤖 pega a primeira tarefa para finalizar (vamos dizer, nosso "arquivo lento" 📝) e continua o que ele tem que fazer com isso.
Depois, ele 🤖 pega a primeira tarefa para finalizar (vamos dizer, nosso "arquivo lento" 📝) e continua o que tem que fazer com ela.
Esse "esperar por algo" normalmente se refere a operações <abbrtitle="Entrada e Saída">I/O</abbr> que são relativamente "lentas" (comparadas a velocidade do processador e da memória RAM), como esperar por:
Esse "esperar por algo" normalmente se refere a operações <abbrtitle="Entrada e Saída">I/O</abbr> que são relativamente "lentas" (comparadas à velocidade do processador e da memória RAM), como esperar por:
* dados do cliente para serem enviados através da rede
* dados enviados pelo seu programa para serem recebidos pelo clente através da rede
* conteúdo de um arquivo no disco pra ser lido pelo sistema e entregar ao seu programa
* dados enviados pelo seu programa serem recebidos pelo clente através da rede
* conteúdo de um arquivo no disco ser lido pelo sistema e entregue ao seu programa
* conteúdo que seu programa deu ao sistema para ser escrito no disco
* uma operação remota API
* uma operação no banco de dados para finalizar
* uma solicitação no banco de dados esperando o retorno do resultado
* uma operação em uma API remota
* uma operação no banco de dados finalizar
* uma solicitação no banco de dados retornar o resultado
* etc.
Enquanto o tempo de execução é consumido mais pela espera das operações <abbrtitle="Entrada e Saída">I/O</abbr>, essas operações são chamadas de operações "limitadas por I/O".
Quanto o tempo de execução é consumido majoritariamente pela espera de operações <abbrtitle="Entrada e Saída">I/O</abbr>, essas operações são chamadas operações "limitadas por I/O".
Isso é chamado de "assíncrono" porquê o computador / programa não tem que ser "sincronizado" com a tarefa lenta, esperando pelo exato momento que a tarefa finalize, enquanto não faz nada, para ser capaz de pegar o resultado da tarefa e dar continuidade ao trabalho.
Isso é chamado de "assíncrono" porque o computador / programa não tem que ser "sincronizado" com a tarefa lenta, esperando pelo momento exato em que a tarefa finaliza, enquanto não faz nada, para ser capaz de pegar o resultado da tarefa e dar continuidade ao trabalho.
Ao invés disso, sendo um sistema "assíncrono", uma vez finalizada, a tarefa pode esperar um pouco (alguns microssegundos) para que o computador / programa finalize o que quer que esteja fazendo,e então volte para pegar o resultado e continue trabalhando com ele.
Ao invés disso, sendo um sistema "assíncrono", uma vez finalizada, a tarefa pode esperar na fila um pouco (alguns microssegundos) para que o computador / programa finalize o que quer que esteja fazendo,e então volte para pegar o resultado e continue trabalhando com ele.
Para "síncrono" (contrário de "assíncrono") também é utilizado o termo "sequencial", porquê o computador / programa segue todos os passos, na sequência, antes de trocar para uma tarefa diferente, mesmo se alguns passos envolvam esperar.
Para "síncrono" (contrário de "assíncrono") também é utilizado o termo "sequencial", porquê o computador / programa segue todos os passos, em sequência, antes de trocar para uma tarefa diferente, mesmo se alguns passos envolvam esperar.
### Concorrência e hambúrgueres
Essa idéia de código **assíncrono** descrito acima é algo às vezes chamado de **"concorrência"**. E é diferente de **"paralelismo"**.
Essa idéia de código **assíncrono** descrita acima é às vezes chamado de **"concorrência"**. Isso é diferente de **"paralelismo"**.
**Concorrência** e **paralelismo** ambos são relacionados a "diferentes coisas acontecendo mais ou menos ao mesmo tempo".
@ -105,117 +105,115 @@ Para ver essa diferença, imagine a seguinte história sobre hambúrgueres:
### Hambúrgueres concorrentes
Você vai com seu _crush_:heart_eyes: na lanchonete, fica na fila enquanto o caixa pega os pedidos das pessoas na sua frente.
Você vai com seu _crush_ na lanchonete, e fica na fila enquanto o caixa pega os pedidos das pessoas na sua frente. 😍
Então chega a sua vez, você pede dois saborosos hambúrgueres para você e seu _crush_ :heart_eyes:.
Então chega a sua vez, você pede dois saborosos hambúrgueres para você e seu _crush_. 🍔🍔
Você paga.
O caixa diz alguma coisa para o cozinheiro na cozinha para que eles saivam que têm que preparar seus hambúrgueres (mesmo que ele esteja atualmente preparando os lanches dos outros clientes).
O caixa diz alguma coisa para o cara na cozinha para que ele tenha que preparar seus hambúrgueres (mesmo embora ele esteja preparando os lanches dos outros clientes).
Você paga. 💸
O caixa te entrega seu número de chamada.
Enquanto você espera, você vai com seu _crush_:heart_eyes: e pega uma mesa, senta e conversa com seu _crush_:heart_eyes: por um bom tempo (como seus hambúrgueres são muito saborosos, leva um tempo para serem preparados).
Enquanto você espera, você vai com seu _crush_ e pega uma mesa, senta e conversa com seu _crush_por um bom tempo (já que seus hambúrgueres são muito saborosos, e leva um tempo para serem preparados).
Enquanto você está sentado na mesa com seu _crush_ :heart_eyes:, esperando os hambúrgueres, você pode gastar o tempo admirando como lindo, maravilhoso e esperto é seu _crush_ :heart_eyes:.
Já que você está sentado na mesa com seu _crush_, esperando os hambúrgueres, você pode passar esse tempo admirando o quão lindo, maravilhoso e esperto é seu _crush_ ✨😍✨.
Enquanto espera e conversa com seu _crush_ :heart_eyes:, de tempos em tempos, você verifica o número de chamada exibido no balcão para ver se já é sua vez.
Enquanto espera e conversa com seu _crush_, de tempos em tempos, você verifica o número da chamada exibido no balcão para ver se já é sua vez.
Então a certo ponto, é finalmente sua vez. Você vai no balcão, pega seus hambúrgueres e volta para a mesa.
Então em algum momento, é finalmente sua vez. Você vai ao balcão, pega seus hambúrgueres e volta para a mesa.
Você e seu _crush_:heart_eyes: comem os hambúrgueres e aproveitam o tempo.
Você e seu _crush_ comem os hambúrgueres e aproveitam o tempo. ✨
---
Imagine que você seja o computador / programa nessa história.
Enquanto você está na fila, tranquilo, esperando por sua vez, não está fazendo nada "produtivo". Mas a fila é rápida porquê o caixa só está pegando os pedidos, então está tudo bem.
Enquanto você está na fila, você está somente ocioso 😴, esperando por sua vez, sem fazer nada muito "produtivo". Mas a fila é rápida porque o caixa só está pegando os pedidos (não os preparando), então está tudo bem.
Então, quando é sua vez, você faz o trabalho "produtivo" de verdade, você processa o menu, decide o que quer, pega a escolha de seu _crush_ :heart_eyes:, paga, verifica se entregou o valor correto em dinheiro ou cartão de crédito, verifica se foi cobrado corretamente, verifica se seu pedido está correto etc.
Então, quando é sua vez, você faz trabalho realmente "produtivo", você processa o menu, decide o que quer, pega a escolha de seu _crush_, paga, verifica se entregou o cartão ou a cédula correta, verifica se foi cobrado corretamente, verifica se seu pedido está correto etc.
Mas então, embora você ainda não tenha os hambúrgueres, seu trabalho no caixa está "pausado", porquê você tem que esperar seus hambúrgueres estarem prontos.
Mas então, embora você ainda não tenha os hambúrgueres, seu trabalho no caixa está "pausado" ⏸, porque você tem que esperar 🕙 seus hambúrgueres ficarem prontos.
Mas enquanto você se afasta do balcão e senta na mesa com o número da sua chamada, você pode trocar sua atenção para seu _crush_ :heart_eyes:, e "trabalhar" nisso. Então você está novamente fazendo algo muito "produtivo", como flertar com seu _crush_:heart_eyes:.
Contudo, à medida que você se afasta do balcão e senta na mesa, com um número para sua chamada, você pode trocar 🔀 sua atenção para seu _crush_, e "trabalhar" ⏯ 🤓 nisso. Então você está novamente fazendo algo muito "produtivo", como flertar com seu _crush_😍.
Então o caixa diz que "seus hambúrgueres estão prontos" colocando seu número no balcão, mas você não corre que nem um maluco imediatamente quando o número exibido é o seu. Você sabe que ninguém irá roubar seus hambúrgueres porquê você tem o número de chamada, e os outros tem os números deles.
Então o caixa 💁 diz que "seus hambúrgueres estão prontos" colocando seu número no balcão, mas você não corre que nem um maluco imediatamente quando o número exibido é o seu. Você sabe que ninguém irá roubar seus hambúrgueres porque você tem o seu número da chamada, e os outros têm os deles.
Então você espera que seu _crush_ :heart_eyes: termine a história que estava contando (terminar o trabalho atual / tarefa sendo processada), sorri gentilmente e diz que você está indo buscar os hambúrgueres.
Então você espera seu _crush_ terminar a história que estava contando (terminar o trabalho atual ⏯ / tarefa sendo processada 🤓), sorri gentilmente e diz que você está indo buscar os hambúrgueres.
Então você vai no balcão, para a tarefa inicial que agora está finalizada, pega os hambúrgueres, e leva para a mesa. Isso finaliza esse passo / tarefa da interação com o balcão. Agora é criada uma nova tarefa, "comer hambúrgueres", mas a tarefa anterior, "pegar os hambúrgueres" já está finalizada.
Então você vai ao balcão 🔀, para a tarefa inicial que agora está finalizada⏯, pega os hambúrgueres, agradece, e leva-os para a mesa. Isso finaliza esse passo / tarefa da interação com o balcão ⏹. Isso, por sua vez, cria uma nova tarefa, a de "comer hambúrgueres" 🔀 ⏯, mas a tarefa anterior de "pegar os hambúrgueres" já está finalizada ⏹.
### Hambúrgueres paralelos
Você vai com seu _crush_ :heart_eyes: em uma lanchonete paralela.
Agora vamos imaginar que esses não são "Hambúrgueres Concorrentes", e sim "Hambúrgueres Paralelos"
Você fica na fila enquanto alguns (vamos dizer 8) caixas pegam os pedidos das pessoas na sua frente.
Você vai com seu _crush_ na lanchonete paralela.
Todo mundo antes de você está esperando pelos hambúrgueres estarem prontos antes de deixar o caixa porquê cada um dos 8 caixas vai e prepara o hambúrguer antes de pegar o próximo pedido.
Você fica na fila enquanto vários (vamos dizer 8) caixas que também são cozinheiros pegam os pedidos das pessoas na sua frente.
Então é finalmente sua vez, e pede 2 hambúrgueres muito saborosos para você e seu _crush_ :heart_eyes:.
Todo mundo na sua frente está esperando seus hambúrgueres ficarem prontos antes de deixar o caixa porque cada um dos 8 caixas vai e prepara o hambúrguer logo após receber o pedido, antes de pegar o próximo pedido.
Você paga.
Então é finalmente sua vez, você pede 2 hambúrgueres muito saborosos para você e seu _crush_.
Você paga 💸.
O caixa vai para a cozinha.
Você espera, na frente do balcão, para que ninguém pegue seus hambúrgueres antes de você, já que não tem números de chamadas.
Você espera, na frente do balcão 🕙, para que ninguém pegue seus hambúrgueres antes de você, já que não tem números de chamadas.
Enquanto você e seu _crush_ :heart_eyes: estão ocupados não permitindo que ninguém passe a frente e pegue seus hambúrgueres assim que estiverem prontos, você não pode dar atenção ao seu _crush_ :heart_eyes:.
Como você e seu _crush_ estão ocupados não permitindo que ninguém passe na frente e pegue seus hambúrgueres assim que estiverem prontos, você não pode dar atenção ao seu _crush_. 😞
Isso é trabalho "síncrono", você está "sincronizado" com o caixa / cozinheiro. Você tem que esperar e estar lá no exato momento que o caixa / cozinheiro terminar os hambúrgueres e dá-los a você, ou então, outro alguém pode pegá-los.
Isso é trabalho "síncrono", você está "sincronizado" com o caixa / cozinheiro👨🍳. Você tem que esperar 🕙 e estar lá no exato momento que o caixa / cozinheiro 👨🍳 terminar os hambúrgueres e os der a você, ou então, outro alguém pode pegá-los.
Então seu caixa / cozinheiro finalmente volta com seus hambúrgueres, depois de um longo tempo esperando por eles em frente ao balcão.
Então seu caixa / cozinheiro 👨🍳 finalmente volta com seus hambúrgueres, depois de um longo tempo esperando 🕙 por eles em frente ao balcão.
Você pega seus hambúrgueres e vai para a mesa com seu _crush_ :heart_eyes:.
Você pega seus hambúrgueres e vai para a mesa com seu _crush_.
Vocês comem os hambúrgueres, e o trabalho está terminado.
Vocês comem os hambúrgueres, e o trabalho está terminado. ⏹
Não houve muita conversa ou flerte já que a maior parte do tempo foi gasto esperando os lanches na frente do balcão.
Não houve muita conversa ou flerte já que a maior parte do tempo foi gasto esperando 🕙 na frente do balcão. 😞
---
Nesse cenário dos hambúrgueres paralelos, você é um computador / programa com dois processadores (você e seu _crush_ :heart_eyes:), ambos esperando e dedicando a atenção de estar "esperando no balcão" por um bom tempo.
Nesse cenário dos hambúrgueres paralelos, você é um computador / programa com dois processadores (você e seu _crush_), ambos esperando 🕙 e dedicando sua atenção ⏯ "esperando no balcão" 🕙 por um bom tempo.
A lanchonete paralela tem 8 processadores (caixas / cozinheiros). Enquanto a lanchonete dos hambúrgueres concorrentes tinham apenas 2 (um caixa e um cozinheiro).
A lanchonete paralela tem 8 processadores (caixas / cozinheiros), enquanto a lanchonete dos hambúrgueres concorrentes tinha apenas 2 (um caixa e um cozinheiro).
Ainda assim, a última experiência não foi a melhor.
Ainda assim, a experiência final não foi a melhor. 😞
---
Essa poderia ser a história paralela equivalente aos hambúrgueres.
Essa seria o equivalente paralelo à histório dos hambúrgueres. 🍔
Para um exemplo "mais real", imagine um banco.
Até recentemente, a maioria dos bancos tinha muitos caixas e uma grande fila.
Até recentemente, a maioria dos bancos tinham muitos caixas 👨💼👨💼👨💼👨💼 e uma grande fila 🕙🕙🕙🕙🕙🕙🕙🕙.
Todos os caixas fazendo todo o trabalho, um cliente após o outro.
Todos os caixas fazendo todo o trabalho, um cliente após o outro 👨💼⏯.
E você tinha que esperar na fila por um longo tempo ou poderia perder a vez.
E você tinha que esperar 🕙 na fila por um longo tempo ou poderia perder a vez.
Você provavelmente não gostaria de levar seu _crush_:heart_eyes: com você para um rolezinho no banco.
Você provavelmente não gostaria de levar seu _crush_😍 com você para um rolezinho no banco 🏦.
### Conclusão dos hambúrgueres
Nesse cenário dos "hambúrgueres com seu _crush_ :heart_eyes:", como tem muita espera, faz mais sentido ter um sistema concorrente.
Nesse cenário dos "hambúrgueres com seu _crush_", como tem muita espera, faz mais sentido ter um sistema concorrente ⏸🔀⏯.
Esse é o caso da maioria das aplicações web.
Geralmente são muitos usuários, e seu servidor está esperando pelas suas conexões não tão boas para enviar as requisições.
E então esperando novamente pelas respostas voltarem.
Essa "espera" é medida em microssegundos, e ainda assim, somando tudo, é um monte de espera no final.
Muitos, muitos usuários, mas seu servidor está esperando 🕙 pela sua conexão não tão boa enviar suas requisições.
Por isso que faz muito mais sentido utilizar código assíncrono para APIs web.
E então esperando 🕙 novamente as respostas voltarem.
A maioria dos frameworks Python existentes mais populares (incluindo Flask e Django) foram criados antes que os novos recursos assíncronos existissem em Python. Então, os meios que eles podem ser colocados em produção para suportar execução paralela mais a forma antiga de execução assíncrona não são tão poderosos quanto as novas capacidades.
Essa "espera" 🕙 é medida em microssegundos, mas ainda assim, somando tudo, é um monte de espera no final.
Mesmo embora a especificação principal para web assíncrono em Python (ASGI) foi desenvolvida no Django, para adicionar suporte para WebSockets.
Por isso que faz bastante sentido utilizar código assíncrono ⏸🔀⏯ para APIs web.
Esse tipo de assincronicidade é o que fez NodeJS popular (embora NodeJS não seja paralelo) e que essa seja a força do Go como uma linguagem de programa.
Esse tipo de assincronicidade é o que fez NodeJS popular (embora NodeJS não seja paralelo) e essa é a força do Go como uma linguagem de programação.
E esse é o mesmo nível de performance que você tem com o **FastAPI**.
E como você pode ter paralelismo e sincronicidade ao mesmo tempo, você tem uma maior performance do que a maioria dos frameworks NodeJS testados e lado a lado com Go, que é uma linguagem compilada próxima ao C <ahref="https://www.techempower.com/benchmarks/#section=data-r17&hw=ph&test=query&l=zijmkf-1"class="external-link"target="_blank">(tudo graças ao Starlette)</a>.
E como você pode ter paralelismo e assincronicidade ao mesmo tempo, você tem uma maior performance do que a maioria dos frameworks NodeJS testados e lado a lado com Go, que é uma linguagem compilada, mais próxima ao C <ahref="https://www.techempower.com/benchmarks/#section=data-r17&hw=ph&test=query&l=zijmkf-1"class="external-link"target="_blank">(tudo graças ao Starlette)</a>.
### Concorrência é melhor que paralelismo?
@ -225,64 +223,64 @@ Concorrência é diferente de paralelismo. E é melhor em cenários **específic
Então, para equilibrar tudo, imagine a seguinte historinha:
> Você tem que limpar uma grande casa suja.
> Você tem que limpar uma casa grande e suja.
*Sim, essa é toda a história*.
---
Não há espera em lugar algum, apenas um monte de trabalho para ser feito, em múltiplos cômodos da casa.
Não há espera 🕙 em lugar algum, apenas um monte de trabalho para ser feito, em múltiplos cômodos da casa.
Você poderia ter chamadas como no exemplo dos hambúrgueres, primeiro a sala de estar, então a cozinha, mas você não está esperando por nada, apenas limpar e limpar, as chamadas não afetariam em nada.
Você poderia ter turnos como no exemplo dos hambúrgueres, primeiro a sala de estar, então a cozinha, mas como você não está esperando por nada, apenas limpando e limpando, as chamadas não afetariam em nada.
Levaria o mesmo tempo para finalizar com ou sem chamadas (concorrência) e você teria feito o mesmo tanto de trabalho.
Levaria o mesmo tempo para finalizar com ou sem turnos (concorrência) e você teria feito o mesmo tanto de trabalho.
Mas nesse caso, se você trouxesse os 8 ex-caixas / cozinheiros / agora-faxineiros, e cada um deles (mais você) pudessem dividir a casa para limpá-la, vocês fariam toda a limpeza em **paralelo**, com a ajuda extra, e terminariam muito mais cedo.
Nesse cenário, cada um dos faxineiros (incluindo você) poderia ser um processador, fazendo a sua parte do trabalho.
E a maior parte do tempo de execução é tomada por trabalho (ao invés de ficar esperando), e o trabalho em um computador é feito pela <abbrtitle="Unidade de Processamento Central">CPU</abbr>, que podem gerar problemas que são chamados de "limite de CPU".
E a maior parte do tempo de execução é tomada por trabalho real (ao invés de ficar esperando), e o trabalho em um computador é feito pela <abbrtitle="Unidade de Processamento Central">CPU</abbr>. Eles chamam esses problemas de "limitados por CPU".
---
Exemplos comuns de limite de CPU são coisas que exigem processamento matemático complexo.
Exemplos comuns de operações limitadas por CPU são coisas que exigem processamento matemático complexo.
Por exemplo:
* **Processamento de áudio** ou **imagem**
* **Visão do Computador**: uma imagem é composta por milhões de pixels, cada pixel tem 3 valores (cores, processamento que normalmente exige alguma computação em todos esses pixels ao mesmo tempo)
* **Visão Computacional**: uma imagem é composta por milhões de pixels, cada pixel tem 3 valores / cores, processar isso normalmente exige alguma computação em todos esses pixels ao mesmo tempo
* **Machine Learning**: Normalmente exige muita multiplicação de matrizes e vetores. Pense numa grande folha de papel com números e multiplicando todos eles juntos e ao mesmo tempo.
* **Machine Learning**: Normalmente exige muita multiplicação de matrizes e vetores. Pense numa grande planilha com números e em multiplicar todos eles juntos e ao mesmo tempo.
* **Deep Learning**: Esse é um subcampo do Machine Learning, então o mesmo se aplica. A diferença é que não há apenas uma grande folha de papel com números para multiplicar, mas um grande conjunto de folhas de papel, e em muitos casos, você utiliza um processador especial para construir e/ou usar modelos.
* **Deep Learning**: Esse é um subcampo do Machine Learning, então, o mesmo se aplica. A diferença é que não há apenas uma grande planilha com números para multiplicar, mas um grande conjunto delas, e em muitos casos, você utiliza um processador especial para construir e/ou usar esses modelos.
### Concorrência + Paralelismo: Web + Machine learning
Com **FastAPI** você pode levar a vantagem da concorrência que é muito comum para desenvolvimento web (o mesmo atrativo de NodeJS).
Mas você também pode explorar os benefícios do paralelismo e multiprocessamento (tendo múltiplos processadores rodando em paralelo) para trabalhos pesados que geram **limite de CPU** como aqueles em sistemas de Machine Learning.
Mas você também pode explorar os benefícios do paralelismo e multiprocessamento (tendo múltiplos processadores rodando em paralelo) para trabalhos **limitados por CPU** como aqueles em sistemas de Machine Learning.
Isso, mais o simples fato que Python é a principal linguagem para **Data Science**, Machine Learning e especialmente Deep Learning, faz do FastAPI uma ótima escolha para APIs web e aplicações com Data Science / Machine Learning (entre muitas outras).
Isso, somado ao simples fato que Python é a principal linguagem para **Data Science**, Machine Learning e especialmente Deep Learning, faz do FastAPI uma ótima escolha para APIs web e aplicações com Data Science / Machine Learning (entre muitas outras).
Para ver como alcançar esse paralelismo em produção veja a seção sobre [Deployment](deployment/index.md){.internal-link target=_blank}.
## `async` e `await`
Versões modernas do Python tem um modo muito intuitivo para definir código assíncrono. Isso faz parecer normal o código "sequencial" e fazer o "esperar" para você nos momentos certos.
Versões modernas do Python têm um modo muito intuitivo para definir código assíncrono. Isso faz parecer do mesmo jeito do código normal "sequencial" e fazer a "espera" para você nos momentos certos.
Quando tem uma operação que exigirá espera antes de dar os resultados e tem suporte para esses recursos Python, você pode escrever assim:
Quando tem uma operação que exigirá espera antes de dar os resultados e tem suporte para esses novos recursos do Python, você pode escrever assim:
```Python
burgers = await get_burgers(2)
```
A chave aqui é o `await`. Ele diz ao Python que ele tem que esperar por `get_burgers(2)`para finalizar suas coisas antes de armazenar os resultados em `burgers`. Com isso, o Python saberá que ele pode ir e fazer outras coisas nesse meio tempo (como receber outra requisição).
A chave aqui é o `await`. Ele diz ao Python que ele tem que esperar por `get_burgers(2)` finalizar suas coisas 🕙 antes de armazenar os resultados em `burgers`. Com isso, o Python saberá que ele pode ir e fazer outras coisas 🔀 ⏯ nesse meio tempo (como receber outra requisição).
Para o `await` funcionar, tem que estar dentro de uma função que suporte essa assincronicidade. Para fazer isso, apenas declare a função com `async def`:
```Python hl_lines="1"
async def get_burgers(number: int):
# Fazer alguma coisa assíncrona para criar os hambúrgueres
# Faz alguma coisa assíncrona para criar os hambúrgueres
Com `async def`, o Python sabe que, dentro dessa função, tem que estar ciente das expressões `await`, e que isso pode "pausar" a execução dessa função, e poderá fazer outra coisa antes de voltar.
Com `async def`, o Python sabe que, dentro dessa função, ele deve estar ciente das expressões `await`, e que isso poderá "pausar" ⏸ a execução dessa função, e ir fazer outra coisa 🔀 antes de voltar.
Quando você quiser chamar uma função `async def`, você tem que "esperar". Então, isso não funcionará:
Quando você quiser chamar uma função `async def`, você tem que "esperar" ela. Então, isso não funcionará:
```Python
# Isso não irá funcionar, porquê get_burgers foi definido com: async def
@ -319,13 +317,24 @@ async def read_burgers():
Você deve ter observado que `await` pode ser usado somente dentro de funções definidas com `async def`.
Mas ao mesmo tempo, funções definidas com `async def` tem que ser aguardadas. Então, funções com `async def` pdem ser chamadas somente dentro de funções definidas com `async def` também.
Mas ao mesmo tempo, funções definidas com `async def` têm que ser "aguardadas". Então, funções com `async def` pdem ser chamadas somente dentro de funções definidas com `async def` também.
Então, sobre o ovo e a galinha, como você chama a primeira função async?
Se você estivar trabalhando com **FastAPI** não terá que se preocupar com isso, porquê essa "primeira" função será a sua *função de operação de rota*, e o FastAPI saberá como fazer a coisa certa.
Mas se você quiser usar `async` / `await` sem FastAPI, <ahref="https://docs.python.org/3/library/asyncio-task.html#coroutine"class="external-link"target="_blank">verifique a documentação oficial Python</a>.
Mas se você quiser usar `async` / `await` sem FastAPI, você também pode fazê-lo.
### Escreva seu próprio código assíncrono
Starlette (e **FastAPI**) são baseados no <ahref="https://anyio.readthedocs.io/en/stable/"class="external-link"target="_blank">AnyIO</a>, o que o torna compatível com ambos o <ahref="https://docs.python.org/3/library/asyncio-task.html"class="external-link"target="_blank">asyncio</a> da biblioteca padrão do Python, e o <ahref="https://trio.readthedocs.io/en/stable/"class="external-link"target="_blank">Trio</a>.
Em particular, você pode usar diretamente o <ahref="https://anyio.readthedocs.io/en/stable/"class="external-link"target="_blank">AnyIO</a> para seus casos de uso avançados de concorrência que requerem padrões mais avançados no seu próprio código.
E até se você não estiver utilizando FastAPI, você também pode escrever suas próprias aplicações assíncronas com o <ahref="https://anyio.readthedocs.io/en/stable/"class="external-link"target="_blank">AnyIO</a> por ser altamente compatível e ganhar seus benefícios (e.g. *concorrência estruturada*).
Eu criei outra biblioteca em cima do AnyIO, como uma fina camada acima, para melhorar um pouco as anotações de tipo e obter melhor **autocompletar**, **erros de linha**, etc. Ela também possui uma introdução amigável e um tutorial para ajudar você a **entender** e escrever **seu próprio código async**: <ahref="https://asyncer.tiangolo.com/"class="external-link"target="_blank">Asyncer</a>. Seria particularmente útil se você precisar **combinar código async com código regular** (bloqueador/síncrono).
### Outras formas de código assíncrono
@ -337,25 +346,25 @@ Essa mesma sintaxe (ou quase a mesma) foi também incluída recentemente em vers
Mas antes disso, controlar código assíncrono era bem mais complexo e difícil.
Nas versões anteriores do Python, você poderia utilizar threads ou <ahref="http://www.gevent.org/"class="external-link"target="_blank">Gevent</a>. Mas o código é um pouco mais complexo de entender, debugar, e pensar sobre.
Nas versões anteriores do Python, você poderia utilizar threads ou <ahref="http://www.gevent.org/"class="external-link"target="_blank">Gevent</a>. Mas o código é bem mais complexo de entender, debugar, e pensar sobre.
Nas versões anteriores do NodeJS / Navegador JavaScript, você poderia utilizar "callbacks". O que leva ao <ahref="http://callbackhell.com/"class="external-link"target="_blank">inferno do callback</a>.
Nas versões anteriores do NodeJS / Navegador JavaScript, você utilizaria "callbacks". O que leva ao <ahref="http://callbackhell.com/"class="external-link"target="_blank">inferno do callback</a>.
## Corrotinas
**Corrotina** é apenas um jeito bonitinho para a coisa que é retornada de uma função `async def`. O Python sabe que é uma função que pode começar e terminar em algum ponto, mas que pode ser pausada internamente também, sempre que tiver um `await` dentro dela.
**Corrotina** é apenas um jeito bonitinho para a coisa que é retornada de uma função `async def`. O Python sabe que é algo como uma função, que pode começar e que vai terminar em algum ponto, mas que pode ser pausada ⏸ internamente também, sempre que tiver um `await` dentro dela.
Mas toda essa funcionalidade de código assíncrono com `async` e `await` é muitas vezes resumida como "corrotina". É comparável ao principal recurso chave do Go, a "Gorotina".
Mas toda essa funcionalidade de código assíncrono com `async` e `await` é muitas vezes resumida como usando "corrotinas". É comparável ao principal recurso chave do Go, a "Gorrotina".
## Conclusão
Vamos ver a mesma frase com o conteúdo cima:
Vamos ver a mesma frase de cima:
> Versões modernas do Python tem suporte para **"código assíncrono"** usando algo chamado **"corrotinas"**, com sintaxe **`async` e `await`**.
> Versões modernas do Python têm suporte para **"código assíncrono"** usando algo chamado **"corrotinas"**, com sintaxe **`async` e `await`**.
Isso pode fazer mais sentido agora.
Isso pode fazer mais sentido agora. ✨
Tudo isso é o que deixa o FastAPI poderoso (através do Starlette) e que o faz ter uma performance impressionante.
Tudo isso é o que empodera o FastAPI (através do Starlette) e que o faz ter uma performance tão impressionante.
## Detalhes muito técnicos
@ -365,25 +374,25 @@ Você pode provavelmente pular isso.
Esses são detalhes muito técnicos de como **FastAPI** funciona por baixo do capô.
Se você tem algum conhecimento técnico (corrotinas, threads, blocking etc) e está curioso sobre como o FastAPI controla o `async def` vs normal `def`, vá em frente.
Se você tem certo conhecimento técnico (corrotinas, threads, blocking etc) e está curioso sobre como o FastAPI controla o `async def` vs normal `def`, vá em frente.
///
### Funções de operação de rota
Quando você declara uma *função de operação de rota* com `def` normal ao invés de `async def`, ela é rodada em uma threadpool externa que então é aguardada, ao invés de ser chamada diretamente (ela poderia bloquear o servidor).
Quando você declara uma *função de operação de rota* com `def` normal ao invés de `async def`, ela é rodada em uma threadpool externa que é então aguardada, ao invés de ser chamada diretamente (já que ela bloquearia o servidor).
Se você está chegando de outro framework assíncrono que não faz o trabalho descrito acima e você está acostumado a definir triviais *funções de operação de rota* com simples `def` para ter um mínimo ganho de performance (cerca de 100 nanosegundos), por favor observe que no **FastAPI** o efeito pode ser bem o oposto. Nesses casos, é melhor usar `async def` a menos que suas *funções de operação de rota* utilizem código que performem bloqueamento <abbrtitle="Input/Output: disco lendo ou escrevendo, comunicações de rede.">IO</abbr>.
Se você está chegando de outro framework assíncrono que não funciona como descrito acima e você está acostumado a definir *funções de operação de rota* triviais somente de computação com simples `def` para ter um mínimo ganho de performance (cerca de 100 nanosegundos), por favor observe que no **FastAPI** o efeito pode ser bem o oposto. Nesses casos, é melhor usar `async def` a menos que suas *funções de operação de rota* utilizem código que performe bloqueamento <abbrtitle="Input/Output: disco lendo ou escrevendo, comunicações de rede.">IO</abbr>.
Ainda, em ambas as situações, as chances são que o **FastAPI**será [ainda mais rápido](index.md#performance){.internal-link target=_blank} do que (ou ao menos comparável a) seus frameworks antecessores.
Ainda, em ambas as situações, as chances são que o **FastAPI** [ainda será mais rápido](index.md#performance){.internal-link target=_blank} do que (ou ao menos comparável a) seu framework anterior.
### Dependências
O mesmo se aplica para as dependências. Se uma dependência tem as funções com padrão `def` ao invés de `async def`, ela é rodada no threadpool externo.
O mesmo se aplica para as [dependências](tutorial/dependencies/index.md){.internal-link target=_blank}. Se uma dependência tem as funções com padrão `def` ao invés de `async def`, ela é rodada no threadpool externo.
### Sub-dependências
Você pode ter múltiplas dependências e sub-dependências exigindo uma a outra (como parâmetros de definições de funções), algumas delas podem ser criadas com `async def` e algumas com `def` normal. Isso ainda poderia funcionar, e aquelas criadas com `def`podem ser chamadas em uma thread externa ao invés de serem "aguardadas".
Você pode ter múltiplas dependências e [sub-dependências](tutorial/dependencies/sub-dependencies.md){.internal-link target=_blank} requisitando uma à outra (como parâmetros de definições de funções), algumas delas podem ser criadas com `async def` e algumas com `def` normal. Isso ainda funcionaria, e aquelas criadas com `def`normal seriam chamadas em uma thread externa (do threadpool) ao invés de serem "aguardadas".
### Outras funções de utilidade
@ -395,6 +404,6 @@ Se sua função de utilidade é uma função normal com `def`, ela será chamada
---
Novamente, esses são detalhes muito técnicos que provavelmente possam ser úteis caso você esteja procurando por eles.
Novamente, esses são detalhes muito técnicos que provavelmente seriam úteis caso você esteja procurando por eles.
Caso contrário, você deve ficar bem com as dicas da seção acima: <ahref="#in-a-hurry">Com pressa?</a>.
Forcodesnippetsorfragments,surroundedbybackticks(`),don't translate the content, keep the original in English. For example, `list`, `dict`, keep them as is.
Thecontentiswritteninmarkdown,writethetranslationinmarkdownaswell.Don't add triple backticks (`) around the generated translation content.
@ -28,8 +35,38 @@ The content is written in markdown, write the translation in markdown as well. D
Whenthere's an example of code, the console or a terminal, normally surrounded by triple backticks and a keyword like "console" or "bash" (e.g. ```console), do not translate the content, keep the original in English.
print(f"Translating {en_path} to {language} ({language_name})")
agent=Agent("openai:gpt-4o")
prompt_segments=[
lang_prompt_content,
general_prompt,
lang_prompt_content,
]
ifold_translation:
prompt_segments.extend(
[
"There's an existing previous translation for this content that is probably outdated with old content or old instructions.",
"Update the translation given your current instructions and the original content.",
"If you have instructions to translate specific terms or phrases in a specific way, please follow those instructions instead of keeping the old and outdated content.",
"Update the translation only where necessary:",
"- If the original English content has changed, reflect that in the translation.",
"- If the previous translation violates current instructions, update it.",
"- Otherwise, preserve the original translation **line-by-line** as-is.",
"Do not:",
"- Rephrase or rewrite correct lines just to improve the style.",
"- Add or remove line breaks unless the English source changed.",
"- Change formatting or whitespace unless absolutely required.",
"Only change what must be changed. The goal is to minimize diffs for easier review.",