Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 4 additions & 42 deletions docs/tutorial/asyncify.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,24 +16,7 @@ Let's see a **broken** example first.

Let's see a sync (regular, blocking) function `do_sync_work()`:

```Python hl_lines="3-5"
# Code above omitted 👆

{!./docs_src/tutorial/asyncify/tutorial001.py[ln:6-8]!}

# Code below omitted 👇
```

<details>
<summary>👀 Full file preview</summary>

```Python
# 🚨 Don't use this, it will block the event loop! 🚨

{!./docs_src/tutorial/asyncify/tutorial001.py!}
```

</details>
{* docs_src/tutorial/asyncify/tutorial001.py ln[8:10] hl[8:10] *}

This function could be talking to a database, a remote API, etc. But it doesn't use `await`, it just makes Python wait there without a warning using `time.sleep(1)`.

Expand All @@ -43,21 +26,15 @@ Here's the problem.

Let's just call that **slow** sync (regular, blocking) function directly from inside the async code 😱:

```Python hl_lines="14"
# 🚨 Don't use this, it will block the event loop! 🚨

{!./docs_src/tutorial/asyncify/tutorial001.py!}
```
{* docs_src/tutorial/asyncify/tutorial001.py hl[14] *}

Because that function is not async, but still it makes Python wait there, it will impede any other async code that could have been started from running. It will all have to **just wait** there doing nothing, wasting computation time. 😭

## Use Asyncify

In those cases where you want to run "**sync**" (synchronous, blocking) code **from inside of async** code in a way that is compatible with the rest of the async code you can use **Asyncer**'s `asyncify()`. 🚀

```Python hl_lines="4 13"
{!./docs_src/tutorial/asyncify/tutorial002.py!}
```
{* docs_src/tutorial/asyncify/tutorial002.py hl[4,13] *}

`asyncify()` takes the **sync (blocking) function** that you want to call and then returns another **async function** that takes the actual **arguments for the original sync function**.

Expand All @@ -67,22 +44,7 @@ Then you can `await` that and get the return value that was **safely** executed

Notice that now the function `do_sync_work` is not an `async` function:

```Python hl_lines="3-5"
# Code above omitted 👆

{!./docs_src/tutorial/asyncify/tutorial002.py[ln:7-9]!}

# Code below omitted 👇
```

<details>
<summary>👀 Full file preview</summary>

```Python
{!./docs_src/tutorial/asyncify/tutorial002.py!}
```

</details>
{* docs_src/tutorial/asyncify/tutorial002.py ln[7:9] hl[7:9] *}

...it even has a line:

Expand Down
38 changes: 3 additions & 35 deletions docs/tutorial/first-steps.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,7 @@ Asyncer is based on **AnyIO**, so let's start with a simple example just using *

Let's start with a simple main async function.

```Python hl_lines="3-4"
# Code above omitted 👆

{!./docs_src/tutorial/first_steps/tutorial001.py[ln:9-11]!}

# Code below omitted 👇
```

<details>
<summary>👀 Full file preview</summary>

```Python
{!./docs_src/tutorial/first_steps/tutorial001.py!}
```

</details>
{* docs_src/tutorial/first_steps/tutorial001.py ln[9:11] hl[9:10] *}

When working with **async** code you normally use `async` and `await`.

Expand All @@ -40,30 +25,13 @@ The function `do_work()` also needs to be declared with `async def` for us to be

For this example, let's simulate that by making `do_work()` wait there for 1 second:

```Python hl_lines="3-4"
# Code above omitted 👆

{!./docs_src/tutorial/first_steps/tutorial001.py[ln:4-11]!}

# Code below omitted 👇
```

<details>
<summary>👀 Full file preview</summary>

```Python
{!./docs_src/tutorial/first_steps/tutorial001.py!}
```

</details>
{* docs_src/tutorial/first_steps/tutorial001.py ln[4:11] hl[4:5] *}

## Run the Main Function

As `main()` is an `async` function, we can't call it directly because we can't `await` it. Instead, we call it with `anyio.run()`:

```Python hl_lines="1 14"
{!./docs_src/tutorial/first_steps/tutorial001.py!}
```
{* docs_src/tutorial/first_steps/tutorial001.py hl[1,14] *}

`anyio.run()` will do everything necessary to call `main()`, handling all the `await` parts, and waiting there until it finishes.

Expand Down
34 changes: 2 additions & 32 deletions docs/tutorial/runnify.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,43 +6,13 @@ Continuing with the last example, let's see the first use case where **Asyncer**

Let's say that now you want your async `main()` function to take arguments:

```Python hl_lines="3"
# Code above omitted 👆

{!./docs_src/tutorial/runnify/tutorial001.py[ln:10-12]!}

# Code below omitted 👇
```

<details>
<summary>👀 Full file preview</summary>

```Python
{!./docs_src/tutorial/runnify/tutorial001.py!}
```

</details>
{* docs_src/tutorial/runnify/tutorial001.py ln[10:12] hl[10] *}

## Runnify with Arguments

Now you can use `asyncer.runnify()` to run this function passing arguments:

```Python hl_lines="3"
# Code above omitted 👆

{!./docs_src/tutorial/runnify/tutorial001.py[ln:15]!}

# Code below omitted 👇
```

<details>
<summary>👀 Full file preview</summary>

```Python
{!./docs_src/tutorial/runnify/tutorial001.py!}
```

</details>
{* docs_src/tutorial/runnify/tutorial001.py ln[15] hl[15] *}

`asyncer.runnify()` takes the **async function** you want to call, and then it returns another function that **takes the positional and keyword arguments** needed, in this case it's just `name="World"`.

Expand Down
102 changes: 6 additions & 96 deletions docs/tutorial/soonify-return.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,7 @@ I'll show you how to do that here. 🤓

Let's see the last example `do_work()` async function we used in the previous chapter:

```Python hl_lines="3-5"
# Code above omitted 👆

{!./docs_src/tutorial/soonify/tutorial002.py[ln:5-7]!}

# Code below omitted 👇
```

<details>
<summary>👀 Full file preview</summary>

```Python
{!./docs_src/tutorial/soonify/tutorial002.py!}
```

</details>
{* docs_src/tutorial/soonify/tutorial002.py ln[5:7] hl[5:7] *}

This function takes a parameter `name` and then it prints a message.

Expand All @@ -39,22 +24,7 @@ But now let's say that we don't really want that function to print the message d

Maybe because we could want to do something else later with the value, or for any other reason:

```Python hl_lines="5-6"
# Code above omitted 👆

{!./docs_src/tutorial/soonify_return/tutorial001.py[ln:5-8]!}

# Code below omitted 👇
```

<details>
<summary>👀 Full file preview</summary>

```Python
{!./docs_src/tutorial/soonify_return/tutorial001.py!}
```

</details>
{* docs_src/tutorial/soonify_return/tutorial001.py ln[5:8] hl[7:8] *}

## Store `SoonValue` Objects

Expand All @@ -66,43 +36,13 @@ task_group.soonify(async_function)(arg1, arg2)

...that call **returns a special object** (an instance of a class `SoonValue`) that you can store in a variable:

```Python hl_lines="11-13"
# Code above omitted 👆

{!./docs_src/tutorial/soonify_return/tutorial001.py[ln:5-15]!}

# Code below omitted 👇
```

<details>
<summary>👀 Full file preview</summary>

```Python
{!./docs_src/tutorial/soonify_return/tutorial001.py!}
```

</details>
{* docs_src/tutorial/soonify_return/tutorial001.py ln[5:15] hl[13:15] *}

## Get the Return Value from `SoonValue` Objects

When one of these async functions started with `soonify()` finishes, the **return value** of the function is **stored** inside the `SoonValue` object, in the **attribute** `soon_value1.value`:

```Python hl_lines="9"
# Code above omitted 👆

{!./docs_src/tutorial/soonify_return/tutorial001.py[ln:11-18]!}

# Code below omitted 👇
```

<details>
<summary>👀 Full file preview</summary>

```Python
{!./docs_src/tutorial/soonify_return/tutorial001.py!}
```

</details>
{* docs_src/tutorial/soonify_return/tutorial001.py ln[11:18] hl[17] *}

After the `async with` block, the **task group** will wait for all of the concurrent functions/tasks to finish **before** any code below is executed.

Expand Down Expand Up @@ -136,22 +76,7 @@ All this **typing support** also means that you can use tools like **mypy** to v

If you try to access the `soon_value1.value` attribute of the `SoonValue` object **inside** the `async with` block, you will **normally get an error**:

```Python hl_lines="8"
# Code above omitted 👆

{!./docs_src/tutorial/soonify_return/tutorial002.py[ln:11-19]!}

# Code below omitted 👇
```

<details>
<summary>👀 Full file preview</summary>

```Python
{!./docs_src/tutorial/soonify_return/tutorial002.py!}
```

</details>
{* docs_src/tutorial/soonify_return/tutorial002.py ln[11:19] hl[16] *}

That will raise an exception like this:

Expand All @@ -176,22 +101,7 @@ Because of that, the `soon_value1.value` attributes of the `SoonValue` objects *

You can check if the value is already available by using the `soon_value.ready` attribute, it will be `True` or `False`:

```Python hl_lines="6-8" linenums="1"
# Code above omitted 👆

{!./docs_src/tutorial/soonify_return/tutorial003.py[ln:11-16]!}

# Code below omitted 👇
```

<details>
<summary>👀 Full file preview</summary>

```Python
{!./docs_src/tutorial/soonify_return/tutorial003.py!}
```

</details>
{* docs_src/tutorial/soonify_return/tutorial003.py ln[11:16] hl[14:16] *}

Here we have an `await` inside the `async with` block. It sleeps for **2 seconds**.

Expand Down
Loading