Почему я могу использовать только ключевое слово await внутри асинхронной функции? - PullRequest
0 голосов
/ 26 августа 2018

Предположим, у меня есть такой код

async def fetch_text() -> str:
    return "text "

async def show_something():
    something = await fetch_text()
    print(something)

Это нормально.Но затем я хочу очистить данные, поэтому я делаю

async def fetch_text() -> str:
    return "text "

def fetch_clean_text(text: str) -> str:
    text = await fetch_text()
    return text.strip(text)

async def show_something():
    something = fetch_clean_text()
    print(something)

(я мог бы очистить текст внутри show_something(), но давайте предположим, что show_something() может печатать много вещей, а не или не должензнать, как правильно их чистить.)

Это, конечно, SyntaxError: 'await' outside async function.Но - если этот код может выполняться - хотя выражение await не помещается в функцию сопрограммы, оно выполняется в контексте единицы.Почему такое поведение недопустимо?

Я вижу одного профи в этом дизайне;в моем последнем примере вы не можете видеть, что тело show_something() делает что-то, что может привести к его приостановке.Но если бы я сделал fetch_clean_text() сопрограммой, это не только усложнило бы ситуацию, но, вероятно, также уменьшило бы производительность.Просто не имеет смысла иметь другую сопрограмму, которая сама по себе не выполняет никаких операций ввода-вывода.Есть ли лучший способ?

1 Ответ

0 голосов
/ 26 августа 2018

Я вижу одного профи в этом дизайне; в моем последнем примере вы не можете видеть это Тело show_something () делает что-то, что может привести к его подвеска.

Именно поэтому он спроектирован таким образом. Написание параллельного кода может быть очень сложным, и авторы asyncio решили, что крайне важно всегда явно отмечать места приостановки в коде.

Эта статья объясняет это в деталях (вы можете начать с параграфа «Получить точку уже»).

Но если бы я сделал fetch_clean_text () сопрограммой, не только это усложняет ситуацию, но, вероятно, также снижает производительность.

Вам нужны сопрограммы почти исключительно, когда вы имеете дело с вводом / выводом. Ввод / вывод всегда занимает намного больше времени, чем накладные расходы на использование сопрограмм. Поэтому я думаю, что можно сказать - нет, по сравнению с вводом-выводом, с которым вы уже работали, вы не потеряете значительное количество времени на выполнение сопрограмм.

Есть ли лучший способ?

Единственный способ, который я могу предложить: максимально разделить логику, которая имеет дело с вводом / выводом (асинхронная часть), от остальной части кода (часть синхронизации).

from typing import Awaitable

def clean_text(text: str) -> str:
    return text.strip(text)

async def fetch_text() -> Awaitable[str]:
    return "text "

async def fetch_clean_text(text: str) -> Awaitable[str]:
    text = await fetch_text()
    return clean_text(text)

async def show_something():
    something = await fetch_clean_text()
    print(something)
...