Предположим, у меня есть такой код
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()
сопрограмму, это не только усложнило бы ситуацию, но, вероятно, также снизило бы производительность. Просто не имеет смысла иметь другую сопрограмму, которая не выполняет никаких операций ввода-вывода. Есть ли способ лучше?
В этом дизайне я вижу одного профессионала; в моем последнем примере вы не можете видеть, что тело show_something() делает что-то, что может привести к его приостановке.
Именно поэтому он и разработал этот путь. Написание параллельного кода может быть очень сложным, и авторы асинхронно решили, что критически важно всегда явно отмечать места приостановки кода.
В этой статье это подробно объясняется (вы можете начать с пункта "Get To The Point Already").
Но если бы я сделал fetch_clean_text() сопрограмму, это не только усложнило бы ситуацию, но, вероятно, также снизило бы производительность.
Вам нужны сопрограммы почти исключительно, когда вы имеете дело с I/O. Для ввода сопрограмм ввода-вывода всегда требуется гораздо больше времени, чем накладные расходы. Поэтому я думаю, это можно сказать - нет, по сравнению с I/O, с которым вы уже имеете дело, вы не потеряете сколько-нибудь значительного времени для использования сопрограмм.
Есть ли способ лучше?
Единственный способ, который я могу предложить: - максимально разделить логику, связанную с I/O (асинхронной частью) с остальной частью кода (часть синхронизации).
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)
await
расписание. Как указано выше, вы можете использовать чистую функцию после извлечения.