Browse Source

🌐 Add Spanish translation for Concurrency and async / await (#1290)

* final touches to async section ES translation

* minor fixes

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* Update docs/es/docs/async.md

Co-Authored-By: Camila Gutierrez <[email protected]>

* 📝 Update async/await docs in EN with emojis

* 📝 Update wording, format, and emojis for async/await in ES

* 🔧 Add async.md to MkDocs for Spanish

Co-authored-by: Camila Gutierrez <[email protected]>
Co-authored-by: Sebastián Ramírez <[email protected]>
pull/1423/head
Alvaro Pernas 5 years ago
committed by GitHub
parent
commit
741de7f927
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 126
      docs/en/docs/async.md
  2. 394
      docs/es/docs/async.md
  3. 1
      docs/es/mkdocs.yml

126
docs/en/docs/async.md

@ -55,7 +55,7 @@ But by following the steps above, it will be able to do some performance optimiz
Modern versions of Python have support for **"asynchronous code"** using something called **"coroutines"**, with **`async` and `await`** syntax.
Let's see that phrase by parts in the sections below, below:
Let's see that phrase by parts in the sections below:
* **Asynchronous Code**
* **`async` and `await`**
@ -94,7 +94,7 @@ For "synchronous" (contrary to "asynchronous") they commonly also use the term "
This idea of **asynchronous** code described above is also sometimes called **"concurrency"**. It is different from **"parallelism"**.
**Concurrency** and **parallelism** both relate to "different things happening more or less at the same time".
**Concurrency** and **parallelism** both relate to "different things happening more or less at the same time".
But the details between *concurrency* and *parallelism* are quite different.
@ -102,107 +102,109 @@ To see the difference, imagine the following story about burgers:
### Concurrent Burgers
You go with your crush to get fast food, you stand in line while the cashier takes the orders from the people in front of you.
You go with your crush 😍 to get fast food 🍔, you stand in line while the cashier 💁 takes the orders from the people in front of you.
Then it's your turn, you place your order of 2 very fancy burgers for your crush and you.
Then it's your turn, you place your order of 2 very fancy burgers 🍔 for your crush 😍 and you.
You pay.
You pay 💸.
The cashier says something to the guy in the kitchen so he knows he has to prepare your burgers (even though he is currently preparing the ones for the previous clients).
The cashier 💁 says something to the guy in the kitchen 👨‍🍳 so he knows he has to prepare your burgers 🍔 (even though he is currently preparing the ones for the previous clients).
The cashier gives you the number of your turn.
The cashier 💁 gives you the number of your turn.
While you are waiting, you go with your crush and pick a table, you sit and talk with your crush for a long time (as your burgers are very fancy and take some time to prepare).
While you are waiting, you go with your crush 😍 and pick a table, you sit and talk with your crush 😍 for a long time (as your burgers are very fancy and take some time to prepare ✨🍔✨).
As you are sitting on the table with your crush, while you wait for the burgers, you can spend that time admiring how awesome, cute and smart your crush is.
As you are sitting on the table with your crush 😍, while you wait for the burgers 🍔, you can spend that time admiring how awesome, cute and smart your crush is ✨😍✨.
While waiting and talking to your crush, from time to time, you check the number displayed on the counter to see if it's your turn already.
While waiting and talking to your crush 😍, from time to time, you check the number displayed on the counter to see if it's your turn already.
Then at some point, it finally is your turn. You go to the counter, get your burgers and come back to the table.
Then at some point, it finally is your turn. You go to the counter, get your burgers 🍔 and come back to the table.
You and your crush eat the burgers and have a nice time.
You and your crush 😍 eat the burgers 🍔 and have a nice time.
---
Imagine you are the computer / program in that story.
Imagine you are the computer / program 🤖 in that story.
While you are at the line, you are just idle, waiting for your turn, not doing anything very "productive". But the line is fast because the cashier is only taking the orders, so that's fine.
While you are at the line, you are just idle 😴, waiting for your turn, not doing anything very "productive". But the line is fast because the cashier 💁 is only taking the orders (not preparing them), so that's fine.
Then, when it's your turn, you do actual "productive" work, you process the menu, decide what you want, get your crush's choice, pay, check that you give the correct bill or card, check that you are charged correctly, check that the order has the correct items, etc.
Then, when it's your turn, you do actual "productive" work 🤓, you process the menu, decide what you want, get your crush's 😍 choice, pay 💸, check that you give the correct bill or card, check that you are charged correctly, check that the order has the correct items, etc.
But then, even though you still don't have your burgers, your work with the cashier is "on pause", because you have to wait for your burgers to be ready.
But then, even though you still don't have your burgers 🍔, your work with the cashier 💁 is "on pause", because you have to wait 🕙 for your burgers to be ready.
But as you go away from the counter and sit on the table with a number for your turn, you can switch your attention to your crush, and "work" on that. Then you are again doing something very "productive", as is flirting with your crush.
But as you go away from the counter and sit on the table with a number for your turn, you can switch 🔀 your attention to your crush 😍, and "work" ⏯ 🤓 on that. Then you are again doing something very "productive" 🤓, as is flirting with your crush 😍.
Then the cashier says "I'm finished with doing the burgers" by putting your number on the counter display, but you don't jump like crazy immediately when the displayed number changes to your turn number. You know no one will steal your burgers because you have the number of your turn, and they have theirs.
Then the cashier 💁 says "I'm finished with doing the burgers" 🍔 by putting your number on the counter's display, but you don't jump like crazy immediately when the displayed number changes to your turn number. You know no one will steal your burgers 🍔 because you have the number of your turn, and they have theirs.
So you wait for your crush to finish the story (finish the current work / task being processed), smile gently and say that you are going for the burgers.
So you wait for your crush 😍 to finish the story (finish the current work / task being processed 🤓), smile gently and say that you are going for the burgers.
Then you go to the counter, to the initial task that is now finished, pick the burgers, say thanks and take them to the table. That finishes that step / task of interaction with the counter. That in turn, creates a new task, of "eating burgers", but the previous one of "getting burgers" is finished.
Then you go to the counter 🔀, to the initial task that is now finished, pick the burgers 🍔, say thanks and take them to the table. That finishes that step / task of interaction with the counter. That in turn, creates a new task, of "eating burgers" 🔀 ⏯, but the previous one of "getting burgers" is finished.
### Parallel Burgers
You go with your crush to get parallel fast food.
Now let's imagine these aren't "Concurrent Burgers", but "Parallel Burgers".
You stand in line while several (let's say 8) cashiers take the orders from the people in front of you.
You go with your crush 😍 to get parallel fast food 🍔.
Everyone before you is waiting for their burgers to be ready before leaving the counter because each of the 8 cashiers goes himself and prepares the burger right away before getting the next order.
You stand in line while several (let's say 8) cashiers that at the same time are cooks 👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳 take the orders from the people in front of you.
Then it's finally your turn, you place your order of 2 very fancy burgers for your crush and you.
Everyone before you is waiting 🕙 for their burgers 🍔 to be ready before leaving the counter because each of the 8 cashiers goes himself and prepares the burger right away before getting the next order.
You pay.
Then it's finally your turn, you place your order of 2 very fancy burgers 🍔 for your crush 😍 and you.
The cashier goes to the kitchen.
You pay 💸.
You wait, standing in front of the counter, so that no one else takes your burgers before you, as there are no numbers for turns.
The cashier goes to the kitchen 👨‍🍳.
As you and your crush are busy not letting anyone get in front of you and take your burgers whenever they arrive, you cannot pay attention to your crush.
You wait, standing in front of the counter 🕙, so that no one else takes your burgers 🍔 before you do, as there are no numbers for turns.
This is "synchronous" work, you are "synchronized" with the cashier/cook. You have to wait and be there at the exact moment that the cashier/cook finishes the burgers and gives them to you, or otherwise, someone else might take them.
As you and your crush 😍 are busy not letting anyone get in front of you and take your burgers whenever they arrive 🕙, you cannot pay attention to your crush 😞.
Then your cashier/cook finally comes back with your burgers, after a long time waiting there in front of the counter.
This is "synchronous" work, you are "synchronized" with the cashier/cook 👨‍🍳. You have to wait 🕙 and be there at the exact moment that the cashier/cook 👨‍🍳 finishes the burgers 🍔 and gives them to you, or otherwise, someone else might take them.
You take your burgers and go to the table with your crush.
Then your cashier/cook 👨‍🍳 finally comes back with your burgers 🍔, after a long time waiting 🕙 there in front of the counter.
You just eat them, and you are done.
You take your burgers 🍔 and go to the table with your crush 😍.
There was not much talk or flirting as most of the time was spent waiting in front of the counter.
You just eat them, and you are done 🍔 ⏹.
There was not much talk or flirting as most of the time was spent waiting 🕙 in front of the counter 😞.
---
In this scenario of the parallel burgers, you are a computer / program with two processors (you and your crush), both waiting and dedicating their attention to be "waiting on the counter" for a long time.
In this scenario of the parallel burgers, you are a computer / program 🤖 with two processors (you and your crush 😍), both waiting 🕙 and dedicating their attention to be "waiting on the counter" 🕙 for a long time.
The fast food store has 8 processors (cashiers/cooks). While the concurrent burgers store might have had only 2 (one cashier and one cook).
The fast food store has 8 processors (cashiers/cooks) 👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳. While the concurrent burgers store might have had only 2 (one cashier and one cook) 💁 👨‍🍳.
But still, the final experience is not the best.
But still, the final experience is not the best 😞.
---
This would be the parallel equivalent story for burgers.
This would be the parallel equivalent story for burgers 🍔.
For a more "real life" example of this, imagine a bank.
Up to recently, most of the banks had multiple cashiers and a big line.
Up to recently, most of the banks had multiple cashiers 👨‍💼👨‍💼👨‍💼👨‍💼 and a big line 🕙🕙🕙🕙🕙🕙🕙🕙.
All of the cashiers doing all the work with one client after the other.
All of the cashiers doing all the work with one client after the other 👨‍💼⏯.
And you have to wait in the line for a long time or you lose your turn.
And you have to wait 🕙 in the line for a long time or you lose your turn.
You probably wouldn't want to take your crush with you to do errands at the bank.
You probably wouldn't want to take your crush 😍 with you to do errands at the bank 🏦.
### Burger Conclusion
In this scenario of "fast food burgers with your crush", as there is a lot of waiting, it makes a lot more sense to have a concurrent system.
In this scenario of "fast food burgers with your crush", as there is a lot of waiting 🕙, it makes a lot more sense to have a concurrent system ⏸🔀⏯.
This is the case for most of the web applications.
Many, many users, but your server is waiting for their not-so-good connection to send their requests.
Many, many users, but your server is waiting 🕙 for their not-so-good connection to send their requests.
And then waiting again for the responses to come back.
And then waiting 🕙 again for the responses to come back.
This "waiting" is measured in microseconds, but still, summing it all, it's a lot of waiting in the end.
This "waiting" 🕙 is measured in microseconds, but still, summing it all, it's a lot of waiting in the end.
That's why it makes a lot of sense to use asynchronous code for web APIs.
That's why it makes a lot of sense to use asynchronous ⏸🔀⏯ code for web APIs.
Most of the existing popular Python frameworks (including Flask and Django) were created before the new asynchronous features in Python existed. So, the ways they can be deployed support parallel execution and an older form of asynchronous execution that is not as powerful as the new capabilities.
@ -210,7 +212,7 @@ Even though the main specification for asynchronous web Python (ASGI) was develo
That kind of asynchronicity is what made NodeJS popular (even though NodeJS is not parallel) and that's the strength of Go as a programing language.
And that's the same level of performance</a> you get with **FastAPI**.
And that's the same level of performance you get with **FastAPI**.
And as you can have parallelism and asynchronicity at the same time, you get higher performance than most of the tested NodeJS frameworks and on par with Go, which is a compiled language closer to C <a href="https://www.techempower.com/benchmarks/#section=data-r17&hw=ph&test=query&l=zijmkf-1" class="external-link" target="_blank">(all thanks to Starlette)</a>.
@ -228,15 +230,15 @@ So, to balance that out, imagine the following short story:
---
There's no waiting anywhere, just a lot of work to be done, on multiple places of the house.
There's no waiting 🕙 anywhere, just a lot of work to be done, on multiple places of the house.
You could have turns as in the burgers example, first the living room, then the kitchen, but as you are not waiting for anything, just cleaning and cleaning, the turns wouldn't affect anything.
You could have turns as in the burgers example, first the living room, then the kitchen, but as you are not waiting 🕙 for anything, just cleaning and cleaning, the turns wouldn't affect anything.
It would take the same amount of time to finish with or without turns (concurrency) and you would have done the same amount of work.
But in this case, if you could bring the 8 ex-cashier/cooks/now-cleaners, and each one of them (plus you) could take a zone of the house to clean it, you could do all the work in **parallel**, with the extra help, and finish much sooner.
But in this case, if you could bring the 8 ex-cashier/cooks/now-cleaners 👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳, and each one of them (plus you) could take a zone of the house to clean it, you could do all the work in **parallel**, with the extra help, and finish much sooner.
In this scenario, each one of the cleaners (including you) would be a processor, doing their part of the job.
In this scenario, each one of the cleaners (including you) would be a processor, doing their part of the job.
And as most of the execution time is taken by actual work (instead of waiting), and the work in a computer is done by a <abbr title="Central Processing Unit">CPU</abbr>, they call these problems "CPU bound".
@ -246,8 +248,8 @@ Common examples of CPU bound operations are things that require complex math pro
For example:
* **Audio** or **image processing**
* **Computer vision**: an image is composed of millions of pixels, each pixel has 3 values / colors, processing that normally requires computing something on those pixels, all at the same time)
* **Audio** or **image processing**.
* **Computer vision**: an image is composed of millions of pixels, each pixel has 3 values / colors, processing that normally requires computing something on those pixels, all at the same time.
* **Machine Learning**: it normally requires lots of "matrix" and "vector" multiplications. Think of a huge spreadsheet with numbers and multiplying all of them together at the same time.
* **Deep Learning**: this is a sub-field of Machine Learning, so, the same applies. It's just that there is not a single spreadsheet of numbers to multiply, but a huge set of them, and in many cases, you use a special processor to build and / or use those models.
@ -271,7 +273,7 @@ When there is an operation that will require waiting before giving the results a
burgers = await get_burgers(2)
```
The key here is the `await`. It tells Python that it has to wait for `get_burgers(2)` to finish doing its thing before storing the results in `burgers`. With that, Python will know that it can go and do something else in the meanwhile (like receiving another request).
The key here is the `await`. It tells Python that it has to wait for `get_burgers(2)` to finish doing its thing 🕙 before storing the results in `burgers`. With that, Python will know that it can go and do something else 🔀 ⏯ in the meanwhile (like receiving another request).
For `await` to work, it has to be inside a function that supports this asynchronicity. To do that, you just declare it with `async def`:
@ -290,7 +292,7 @@ def get_sequential_burgers(number: int):
return burgers
```
With `async def`, Python knows that, inside that function, it has to be aware of `await` expressions, and that it can "pause" the execution of that function and go do something else before coming back.
With `async def`, Python knows that, inside that function, it has to be aware of `await` expressions, and that it can "pause" the execution of that function and go do something else 🔀 before coming back.
When you want to call an `async def` function, you have to "await" it. So, this won't work:
@ -338,7 +340,7 @@ In previous versions of NodeJS / Browser JavaScript, you would have used "callba
## Coroutines
**Coroutine** is just the very fancy term for the thing returned by an `async def` function. Python knows that it is something like a function that it can start and that it will end at some point, but that it might be paused internally too, whenever there is an `await` inside of it.
**Coroutine** is just the very fancy term for the thing returned by an `async def` function. Python knows that it is something like a function that it can start and that it will end at some point, but that it might be paused internally too, whenever there is an `await` inside of it.
But all this functionality of using asynchronous code with `async` and `await` is many times summarized as using "coroutines". It is comparable to the main key feature of Go, the "Goroutines".
@ -348,7 +350,7 @@ Let's see the same phrase from above:
> Modern versions of Python have support for **"asynchronous code"** using something called **"coroutines"**, with **`async` and `await`** syntax.
That should make more sense now.
That should make more sense now.
All that is what powers FastAPI (through Starlette) and what makes it have such an impressive performance.
@ -356,16 +358,16 @@ All that is what powers FastAPI (through Starlette) and what makes it have such
!!! warning
You can probably skip this.
These are very technical details of how **FastAPI** works underneath.
If you have quite some technical knowledge (co-routines, threads, blocking, etc) and are curious about how FastAPI handles `async def` vs normal `def`, go ahead.
### Path operation functions
When you declare a *path operation function* with normal `def` instead of `async def`, it is run in an external threadpool that is then awaited, instead of being called directly (as it would block the server).
If you are coming from another async framework that does not work in the way described above and you are used to define trivial compute-only *path operation functions* with plain `def` for a tiny performance gain (about 100 nanoseconds), please note that in **FastAPI** the effect would be quite opposite. In these cases, it's better to use `async def` unless your *path operation functions* use code that performs blocking <abbr title="Input/Output: disk reading or writing, network communications.">IO</abbr>.
If you are coming from another async framework that does not work in the way described above and you are used to define trivial compute-only *path operation functions* with plain `def` for a tiny performance gain (about 100 nanoseconds), please note that in **FastAPI** the effect would be quite opposite. In these cases, it's better to use `async def` unless your *path operation functions* use code that performs blocking <abbr title="Input/Output: disk reading or writing, network communications.">I/O</abbr>.
Still, in both situations, chances are that **FastAPI** will [still be faster](/#performance){.internal-link target=_blank} than (or at least comparable to) your previous framework.
@ -375,7 +377,7 @@ The same applies for dependencies. If a dependency is a standard `def` function
### Sub-dependencies
You can have multiple dependencies and sub-dependencies requiring each other (as parameters of the function definitions), some of them might be created with `async def` and some with normal `def`. It would still work, and the ones created with normal `def` would be called on an external thread instead of being "awaited".
You can have multiple dependencies and sub-dependencies requiring each other (as parameters of the function definitions), some of them might be created with `async def` and some with normal `def`. It would still work, and the ones created with normal `def` would be called on an external thread (from the threadpool) instead of being "awaited".
### Other utility functions
@ -383,7 +385,7 @@ Any other utility function that you call directly can be created with normal `de
This is in contrast to the functions that FastAPI calls for you: *path operation functions* and dependencies.
If your utility function is a normal function with `def`, it will be called directly (as you write it in your code), not in a threadpool, if the function is created with `async def` then you should await for that function when you call it in your code.
If your utility function is a normal function with `def`, it will be called directly (as you write it in your code), not in a threadpool, if the function is created with `async def` then you should `await` for that function when you call it in your code.
---

394
docs/es/docs/async.md

@ -0,0 +1,394 @@
# Concurrencia y async / await
Detalles sobre la sintaxis `async def` para *path operation functions* y un poco de información sobre código asíncrono, concurrencia y paralelismo.
## ¿Tienes prisa?
<abbr title="too long; didn't read"><strong>TL;DR:</strong></abbr>
Si estás utilizando libraries de terceros que te dicen que las llames con `await`, del tipo:
```Python
results = await some_library()
```
Entonces declara tus *path operation functions* con `async def` de la siguiente manera:
```Python hl_lines="2"
@app.get('/')
async def read_results():
results = await some_library()
return results
```
!!! note "Nota"
Solo puedes usar `await` dentro de funciones creadas con `async def`.
---
Si estás utilizando libraries de terceros que se comunican con algo (una base de datos, una API, el sistema de archivos, etc.) y no tienes soporte para `await` (este es el caso para la mayoría de las libraries de bases de datos), declara tus *path operation functions* de forma habitual, con solo `def`, de la siguiente manera:
```Python hl_lines="2"
@app.get('/')
def results():
results = some_library()
return results
```
---
Si tu aplicación (de alguna manera) no tiene que comunicarse con nada más y en consecuencia esperar a que responda, usa `async def`.
---
Si simplemente no lo sabes, usa `def` normal.
---
**Nota**: puedes mezclar `def` y `async def` en tus *path operation functions* tanto como lo necesites y definir cada una utilizando la mejor opción para ti. FastAPI hará lo correcto con ellos.
De todos modos, en cualquiera de los casos anteriores, FastAPI seguirá funcionando de forma asíncrona y será extremadamente rápido.
Pero siguiendo los pasos anteriores, FastAPI podrá hacer algunas optimizaciones de rendimiento.
## Detalles Técnicos
Las versiones modernas de Python tienen soporte para **"código asíncrono"** usando algo llamado **"coroutines"**, usando la sintaxis **`async` y `await`**.
Veamos esa frase por partes en las secciones siguientes:
* **Código Asíncrono**
* **`async` y `await`**
* **Coroutines**
## Código Asíncrono
El código asíncrono sólo significa que el lenguaje 💬 tiene una manera de decirle al sistema / programa 🤖 que, en algún momento del código, 🤖 tendrá que esperar a que *algo más* termine en otro sitio. Digamos que ese *algo más* se llama, por ejemplo, "archivo lento" 📝.
Durante ese tiempo, el sistema puede hacer otras cosas, mientras "archivo lento" 📝 termina.
Entonces el sistema / programa 🤖 volverá cada vez que pueda, sea porque está esperando otra vez, porque 🤖 ha terminado todo el trabajo que tenía en ese momento. Y 🤖 verá si alguna de las tareas por las que estaba esperando ha terminado, haciendo lo que tenía que hacer.
Luego, 🤖 cogerá la primera tarea finalizada (digamos, nuestro "archivo lento" 📝) y continuará con lo que tenía que hacer con esa tarea.
Esa "espera de otra cosa" normalmente se refiere a operaciones <abbr title = "Input and Output, en español: Entrada y Salida.">I/O</abbr> que son relativamente "lentas" (en relación a la velocidad del procesador y memoria RAM), como por ejemplo esperar por:
* los datos de cliente que se envían a través de la red
* los datos enviados por tu programa para ser recibidos por el cliente a través de la red
* el contenido de un archivo en disco para ser leído por el sistema y entregado al programa
* los contenidos que tu programa da al sistema para ser escritos en disco
* una operación relacionada con una API remota
* una operación de base de datos
* el retorno de resultados de una consulta de base de datos
* etc.
Como el tiempo de ejecución se consume principalmente al esperar a operaciones de <abbr title = "Input and Output">I/O</abbr>, las llaman operaciones "<abbr title="atadas a Entrada y Salida">I/O bound</abbr>".
Se llama "asíncrono" porque el sistema / programa no tiene que estar "sincronizado" con la tarea lenta, esperando el momento exacto en que finaliza la tarea, sin hacer nada, para poder recoger el resultado de la tarea y continuar el trabajo.
En lugar de eso, al ser un sistema "asíncrono", una vez finalizada, la tarea puede esperar un poco en la cola (algunos microsegundos) para que la computadora / programa termine lo que estaba haciendo, y luego vuelva para recoger los resultados y seguir trabajando con ellos.
Por "síncrono" (contrario a "asíncrono") también se usa habitualmente el término "secuencial", porque el sistema / programa sigue todos los pasos secuencialmente antes de cambiar a una tarea diferente, incluso si esos pasos implican esperas.
### Concurrencia y Hamburguesas
El concepto de código **asíncrono** descrito anteriormente a veces también se llama **"concurrencia"**. Es diferente del **"paralelismo"**.
**Concurrencia** y **paralelismo** ambos se relacionan con "cosas diferentes que suceden más o menos al mismo tiempo".
Pero los detalles entre *concurrencia* y *paralelismo* son bastante diferentes.
Para entender las diferencias, imagina la siguiente historia sobre hamburguesas:
### Hamburguesas Concurrentes
Vas con la persona que te gusta 😍 a pedir comida rápida 🍔, haces cola mientras el cajero 💁 recoge los pedidos de las personas de delante tuyo.
Llega tu turno, haces tu pedido de 2 hamburguesas impresionantes para esa persona 😍 y para ti.
Pagas 💸.
El cajero 💁 le dice algo al chico de la cocina 👨‍🍳 para que sepa que tiene que preparar tus hamburguesas 🍔 (a pesar de que actualmente está preparando las de los clientes anteriores).
El cajero 💁 te da el número de tu turno.
Mientras esperas, vas con esa persona 😍 y eliges una mesa, se sientan y hablan durante un rato largo (ya que las hamburguesas son muy impresionantes y necesitan un rato para prepararse ✨🍔✨).
Mientras te sientas en la mesa con esa persona 😍, esperando las hamburguesas 🍔, puedes disfrutar ese tiempo admirando lo increíble, inteligente, y bien que se ve ✨😍✨.
Mientras esperas y hablas con esa persona 😍, de vez en cuando, verificas el número del mostrador para ver si ya es tu turno.
Al final, en algún momento, llega tu turno. Vas al mostrador, coges tus hamburguesas 🍔 y vuelves a la mesa.
Tú y esa persona 😍 se comen las hamburguesas 🍔 y la pasan genial ✨.
---
Imagina que eres el sistema / programa 🤖 en esa historia.
Mientras estás en la cola, estás quieto 😴, esperando tu turno, sin hacer nada muy "productivo". Pero la línea va rápida porque el cajero 💁 solo recibe los pedidos (no los prepara), así que está bien.
Luego, cuando llega tu turno, haces un trabajo "productivo" real 🤓, procesas el menú, decides lo que quieres, lo que quiere esa persona 😍, pagas 💸, verificas que das el billete o tarjeta correctos, verificas que te cobren correctamente, que el pedido tiene los artículos correctos, etc.
Pero entonces, aunque aún no tienes tus hamburguesas 🍔, el trabajo hecho con el cajero 💁 está "en pausa" ⏸, porque debes esperar 🕙 a que tus hamburguesas estén listas.
Pero como te alejas del mostrador y te sientas en la mesa con un número para tu turno, puedes cambiar tu atención 🔀 a esa persona 😍 y "trabajar" ⏯ 🤓 en eso. Entonces nuevamente estás haciendo algo muy "productivo" 🤓, como coquetear con esa persona 😍.
Después, el 💁 cajero dice "he terminado de hacer las hamburguesas" 🍔 poniendo tu número en la pantalla del mostrador, pero no saltas al momento que el número que se muestra es el tuyo. Sabes que nadie robará tus hamburguesas 🍔 porque tienes el número de tu turno y ellos tienen el suyo.
Así que esperas a que esa persona 😍 termine la historia (terminas el trabajo actual ⏯ / tarea actual que se está procesando 🤓), sonríes gentilmente y le dices que vas por las hamburguesas ⏸.
Luego vas al mostrador 🔀, a la tarea inicial que ya está terminada ⏯, recoges las hamburguesas 🍔, les dices gracias y las llevas a la mesa. Eso termina esa fase / tarea de interacción con el mostrador ⏹. Eso a su vez, crea una nueva tarea, "comer hamburguesas" 🔀 ⏯, pero la anterior de "conseguir hamburguesas" está terminada ⏹.
### Hamburguesas Paralelas
Ahora imagina que estas no son "Hamburguesas Concurrentes" sino "Hamburguesas Paralelas".
Vas con la persona que te gusta 😍 por comida rápida paralela 🍔.
Haces la cola mientras varios cajeros (digamos 8) que a la vez son cocineros 👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳 toman los pedidos de las personas que están delante de ti.
Todos los que están antes de ti están esperando 🕙 que sus hamburguesas 🍔 estén listas antes de dejar el mostrador porque cada uno de los 8 cajeros prepara la hamburguesa de inmediato antes de recibir el siguiente pedido.
Entonces finalmente es tu turno, haces tu pedido de 2 hamburguesas 🍔 impresionantes para esa persona 😍 y para ti.
Pagas 💸.
El cajero va a la cocina 👨‍🍳.
Esperas, de pie frente al mostrador 🕙, para que nadie más recoja tus hamburguesas 🍔, ya que no hay números para los turnos.
Como tu y esa persona 😍 están ocupados en impedir que alguien se ponga delante y recoja tus hamburguesas apenas llegan 🕙, tampoco puedes prestarle atención a esa persona 😞.
Este es un trabajo "síncrono", estás "sincronizado" con el cajero / cocinero 👨‍🍳. Tienes que esperar y estar allí en el momento exacto en que el cajero / cocinero 👨‍🍳 termina las hamburguesas 🍔 y te las da, o de lo contrario, alguien más podría cogerlas.
Luego, el cajero / cocinero 👨‍🍳 finalmente regresa con tus hamburguesas 🍔, después de mucho tiempo esperando 🕙 frente al mostrador.
Cojes tus hamburguesas 🍔 y vas a la mesa con esa persona 😍.
Sólo las comes y listo 🍔 ⏹.
No has hablado ni coqueteado mucho, ya que has pasado la mayor parte del tiempo esperando 🕙 frente al mostrador 😞.
---
En este escenario de las hamburguesas paralelas, tú eres un sistema / programa 🤖 con dos procesadores (tú y la persona que te gusta 😍), ambos esperando 🕙 y dedicando su atención ⏯ a estar "esperando en el mostrador" 🕙 durante mucho tiempo.
La tienda de comida rápida tiene 8 procesadores (cajeros / cocineros) 👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳. Mientras que la tienda de hamburguesas concurrentes podría haber tenido solo 2 (un cajero y un cocinero) 💁 👨‍🍳.
Pero aún así, la experiencia final no es la mejor 😞.
---
Esta sería la historia paralela equivalente de las hamburguesas 🍔.
Para un ejemplo más "real" de ésto, imagina un banco.
Hasta hace poco, la mayoría de los bancos tenían varios cajeros 👨‍💼👨‍💼👨‍💼👨‍💼 y una gran línea 🕙🕙🕙🕙🕙🕙🕙🕙.
Todos los cajeros haciendo todo el trabajo con un cliente tras otro 👨‍💼⏯.
Y tienes que esperar 🕙 en la fila durante mucho tiempo o perderás tu turno.
Probablemente no querrás llevar contigo a la persona que te gusta 😍 a hacer encargos al banco 🏦.
### Conclusión de las Hamburguesa
En este escenario de "hamburguesas de comida rápida con tu pareja", debido a que hay mucha espera 🕙, tiene mucho más sentido tener un sistema con concurrencia ⏸🔀⏯.
Este es el caso de la mayoría de las aplicaciones web.
Muchos, muchos usuarios, pero el servidor está esperando 🕙 el envío de las peticiones ya que su conexión no es buena.
Y luego esperando 🕙 nuevamente a que las respuestas retornen.
Esta "espera" 🕙 se mide en microsegundos, pero aun así, sumando todo, al final es mucha espera.
Es por eso que tiene mucho sentido usar código asíncrono ⏸🔀⏯ para las API web.
La mayoría de los framework populares de Python existentes (incluidos Flask y Django) se crearon antes de que existieran las nuevas funciones asíncronas en Python. Por lo tanto, las formas en que pueden implementarse admiten la ejecución paralela y una forma más antigua de ejecución asíncrona que no es tan potente como la actual.
A pesar de que la especificación principal para Python web asíncrono (ASGI) se desarrolló en Django, para agregar soporte para WebSockets.
Ese tipo de asincronía es lo que hizo popular a NodeJS (aunque NodeJS no es paralelo) y esa es la fortaleza de Go como lenguaje de programación.
Y ese es el mismo nivel de rendimiento que obtienes con **FastAPI**.
Y como puede tener paralelismo y asincronía al mismo tiempo, obtienes un mayor rendimiento que la mayoría de los frameworks de NodeJS probados y a la par con Go, que es un lenguaje compilado más cercano a C <a href="https://www.techempower.com/benchmarks/#section=data-r17&hw=ph&test=query&l=zijmkf-1" class="external-link" target="_blank">(todo gracias Starlette)</a>.
### ¿Es la concurrencia mejor que el paralelismo?
¡No! Esa no es la moraleja de la historia.
La concurrencia es diferente al paralelismo. Y es mejor en escenarios **específicos** que implican mucha espera. Debido a eso, generalmente es mucho mejor que el paralelismo para el desarrollo de aplicaciones web. Pero no para todo.
Entonces, para explicar eso, imagina la siguiente historia corta:
> Tienes que limpiar una casa grande y sucia.
*Sí, esa es toda la historia*.
---
No hay esperas 🕙, solo hay mucho trabajo por hacer, en varios lugares de la casa.
Podrías tener turnos como en el ejemplo de las hamburguesas, primero la sala de estar, luego la cocina, pero como no estás esperando nada, solo limpiando y limpiando, los turnos no afectarían nada.
Tomaría la misma cantidad de tiempo terminar con o sin turnos (concurrencia) y habrías hecho la misma cantidad de trabajo.
Pero en este caso, si pudieras traer a los 8 ex cajeros / cocineros / ahora limpiadores 👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳👨‍🍳, y cada uno de ellos (y tú) podría tomar una zona de la casa para limpiarla, podría hacer todo el trabajo en **paralelo**, con la ayuda adicional y terminar mucho antes.
En este escenario, cada uno de los limpiadores (incluido tú) sería un procesador, haciendo su parte del trabajo.
Y como la mayor parte del tiempo de ejecución lo coge el trabajo real (en lugar de esperar), y el trabajo en un sistema lo realiza una <abbr title = "Central Processing Unit. En español: Unidad Central de Procesamiento."> CPU </abbr>, a estos problemas se les llama "<abbr title="En español: atado a CPU.">CPU bond</abbr>".
---
Ejemplos típicos de operaciones dependientes de CPU son cosas que requieren un procesamiento matemático complejo.
Por ejemplo:
* **Audio** o **procesamiento de imágenes**.
* **Visión por computadora**: una imagen está compuesta de millones de píxeles, cada píxel tiene 3 valores / colores, procesamiento que normalmente requiere calcular algo en esos píxeles, todo al mismo tiempo.
* **Machine Learning**: normalmente requiere muchas multiplicaciones de "matrices" y "vectores". Imagina en una enorme hoja de cálculo con números y tener que multiplicarlos todos al mismo tiempo.
* **Deep Learning**: este es un subcampo de Machine Learning, por lo tanto, aplica lo mismo. Es solo que no hay una sola hoja de cálculo de números para multiplicar, sino un gran conjunto de ellas, y en muchos casos, usa un procesador especial para construir y / o usar esos modelos.
### Concurrencia + Paralelismo: Web + Machine Learning
Con **FastAPI** puedes aprovechar la concurrencia que es muy común para el desarrollo web (atractivo principal de NodeJS).
Pero también puedes aprovechar los beneficios del paralelismo y el multiprocesamiento (tener múltiples procesos ejecutándose en paralelo) para cargas de trabajo **CPU bond** como las de los sistemas de Machine Learning.
Eso, más el simple hecho de que Python es el lenguaje principal para **Data Science**, Machine Learning y especialmente Deep Learning, hacen de FastAPI una muy buena combinación para las API y aplicaciones web de Data Science / Machine Learning (entre muchas otras).
Para ver cómo lograr este paralelismo en producción, consulta la sección sobre [Despliegue](deployment.md){.internal-link target=_blank}.
## `async` y `await`
Las versiones modernas de python tienen una forma muy intuitiva de definir código asíncrono. Esto hace que se vea como un código "secuencial" normal y que haga la "espera" por ti en los momentos correctos.
Cuando hay una operación que requerirá esperar antes de dar los resultados y tiene soporte para estas nuevas características de Python, puedes programarlo como:
```Python
burgers = await get_burgers(2)
```
La clave aquí es `await`. Eso le dice a Python que tiene que esperar ⏸ a que `get_burgers (2)` termine de hacer lo suyo 🕙 antes de almacenar los resultados en `hamburguesas`. Con eso, Python sabrá que puede ir y hacer otra cosa 🔀 ⏯ mientras tanto (como recibir otra solicitud).
Para que `await` funcione, tiene que estar dentro de una función que admita esta asincronía. Para hacer eso, simplemente lo declaras con `async def`:
```Python hl_lines="1"
async def get_burgers(number: int):
# Do some asynchronous stuff to create the burgers
return burgers
```
...en vez de `def`:
```Python hl_lines="2"
# This is not asynchronous
def get_sequential_burgers(number: int):
# Do some sequential stuff to create the burgers
return burgers
```
Con `async def`, Python sabe que, dentro de esa función, debe tener en cuenta las expresiones `wait` y que puede "pausar" ⏸ la ejecución de esa función e ir a hacer otra cosa 🔀 antes de regresar.
Cuando desees llamar a una función `async def`, debes "esperarla". Entonces, esto no funcionará:
```Python
# Esto no funcionará, porque get_burgers se definió con: async def
hamburguesas = get_burgers (2)
```
---
Por lo tanto, si estás utilizando una library que te dice que puedes llamarla con `await`, debes crear las *path operation functions* que la usan con `async def`, como en:
```Python hl_lines="2 3"
@app.get('/burgers')
async def read_burgers():
burgers = await get_burgers(2)
return burgers
```
### Más detalles técnicos
Es posible que hayas notado que `await` solo se puede usar dentro de las funciones definidas con `async def`.
Pero al mismo tiempo, las funciones definidas con `async def` deben ser "esperadas". Por lo tanto, las funciones con `async def` solo se pueden invocar dentro de las funciones definidas con `async def` también.
Entonces, relacionado con la paradoja del huevo y la gallina, ¿cómo se llama a la primera función `async`?
Si estás trabajando con **FastAPI** no tienes que preocuparte por eso, porque esa "primera" función será tu *path operation function*, y FastAPI sabrá cómo hacer lo pertinente.
En el caso de que desees usar `async` / `await` sin FastAPI, <a href="https://docs.python.org/3/library/asyncio-task.html#coroutine" class="external-link" target="_blank">revisa la documentación oficial de Python</a>.
### Otras formas de código asíncrono
Este estilo de usar `async` y `await` es relativamente nuevo en el lenguaje.
Pero hace que trabajar con código asíncrono sea mucho más fácil.
Esta misma sintaxis (o casi idéntica) también se incluyó recientemente en las versiones modernas de JavaScript (en Browser y NodeJS).
Pero antes de eso, manejar código asíncrono era bastante más complejo y difícil.
En versiones anteriores de Python, podrías haber utilizado <abbr title="En español: hilos.">threads</abbr> o <a href="http://www.gevent.org/" class="external-link" target="_blank">Gevent</a>. Pero el código es mucho más complejo de entender, depurar y desarrollar.
En versiones anteriores de NodeJS / Browser JavaScript, habrías utilizado "callbacks". Lo que conduce a <a href="http://callbackhell.com/" class="external-link" target="_blank">callback hell</a>.
## Coroutines
**Coroutine** es un término sofisticado para referirse a la cosa devuelta por una función `async def`. Python sabe que es algo así como una función que puede iniciar y que terminará en algún momento, pero que también podría pausarse ⏸ internamente, siempre que haya un `await` dentro de ella.
Pero toda esta funcionalidad de usar código asincrónico con `async` y `await` se resume muchas veces como usar "coroutines". Es comparable a la característica principal de Go, las "Goroutines".
## Conclusión
Veamos la misma frase de arriba:
> Las versiones modernas de Python tienen soporte para **"código asíncrono"** usando algo llamado **"coroutines"**, con la sintaxis **`async` y `await`**.
Eso ya debería tener más sentido ahora. ✨
Todo eso es lo que impulsa FastAPI (a través de Starlette) y lo que hace que tenga un rendimiento tan impresionante.
## Detalles muy técnicos
!!! warning "Advertencia"
Probablemente puedas saltarte esto.
Estos son detalles muy técnicos de cómo **FastAPI** funciona a muy bajo nivel.
Si tienes bastante conocimiento técnico (coroutines, threads, bloqueos, etc.) y tienes curiosidad acerca de cómo FastAPI gestiona `async def` vs `def` normal, continúa.
### Path operation functions
Cuando declaras una *path operation function* con `def` normal en lugar de `async def`, se ejecuta en un threadpool externo que luego es "<abbr title="En español: esperado. Usando await.">awaited</abbr>", en lugar de ser llamado directamente (ya que bloquearía el servidor).
Si vienes de otro framework asíncrono que no funciona de la manera descrita anteriormente y estás acostumbrado a definir *path operation functions* del tipo sólo cálculo con `def` simple para una pequeña ganancia de rendimiento (aproximadamente 100 nanosegundos), ten en cuenta que en **FastAPI** el efecto sería bastante opuesto. En estos casos, es mejor usar `async def` a menos que tus *path operation functions* usen un código que realice el bloqueo <abbr title="Input/Output: disk reading or writing, network communications.">I/O</abbr>.
Aún así, en ambas situaciones, es probable que **FastAPI** sea [aún más rápido](/#rendimiento){.Internal-link target=_blank} que (o al menos comparable) a tu framework anterior.
### Dependencias
Lo mismo se aplica para las dependencias. Si una dependencia es una función estándar `def` en lugar de `async def`, se ejecuta en el threadpool externo.
### Subdependencias
Puedes tener múltiples dependencias y subdependencias que se requieren unas a otras (como parámetros de las definiciones de cada función), algunas de ellas pueden crearse con `async def` y otras con `def` normal. Igual todo seguiría funcionando correctamente, y las creadas con `def` normal se llamarían en un thread externo (del threadpool) en lugar de ser "awaited".
### Otras funciones de utilidades
Cualquier otra función de utilidad que llames directamente se puede crear con `def` o `async def` normales y FastAPI no afectará la manera en que la llames.
Esto contrasta con las funciones que FastAPI llama por ti: las *path operation functions* y dependencias.
Si tu función de utilidad es creada con `def` normal, se llamará directamente (tal cual la escribes en tu código), no en un threadpool, si la función se crea con `async def`, entonces debes usar `await` con esa función cuando la llamas en tu código.
---
Nuevamente, estos son detalles muy técnicos que probablemente sólo son útiles si los viniste a buscar expresamente.
De lo contrario, la guía de la sección anterior debería ser suficiente: <a href="#in-a-hurry">¿Tienes prisa?</a>.

1
docs/es/mkdocs.yml

@ -30,6 +30,7 @@ nav:
- tutorial/index.md
- Guía de Usuario Avanzada:
- advanced/index.md
- async.md
markdown_extensions:
- toc:
permalink: true

Loading…
Cancel
Save