Запустить асинхронную задачу сейчас, подождать позжеPython

Программы на Python
Ответить
Anonymous
 Запустить асинхронную задачу сейчас, подождать позже

Сообщение Anonymous »

Программист C# пытается изучить Python. Я пытаюсь запустить расчет с интенсивным использованием процессора, позволяя асинхронному методу, связанному с вводом-выводом, тихо работать в фоновом режиме. В C# я обычно устанавливаю ожидаемое действие, затем запускаю код, интенсивно использующий процессор, затем жду задачи ввода-вывода, а затем объединяю результаты.

Вот как я бы это сделал это на C#

static async Task DoStuff() {
var ioBoundTask = DoIoBoundWorkAsync();
int cpuBoundResult = DoCpuIntensizeCalc();
int ioBoundResult = await ioBoundTask.ConfigureAwait(false);

Console.WriteLine($"The result is {cpuBoundResult + ioBoundResult}");
}

static async Task DoIoBoundWorkAsync() {
Console.WriteLine("Make API call...");
await Task.Delay(2500).ConfigureAwait(false); // non-blocking async call
Console.WriteLine("Data back.");
return 1;
}

static int DoCpuIntensizeCalc() {
Console.WriteLine("Do smart calc...");
Thread.Sleep(2000); // blocking call. e.g. a spinning loop
Console.WriteLine("Calc finished.");
return 2;
}


А вот эквивалентный код на Python

import time
import asyncio

async def do_stuff():
ioBoundTask = do_iobound_work_async()
cpuBoundResult = do_cpu_intensive_calc()
ioBoundResult = await ioBoundTask
print(f"The result is {cpuBoundResult + ioBoundResult}")

async def do_iobound_work_async():
print("Make API call...")
await asyncio.sleep(2.5) # non-blocking async call
print("Data back.")
return 1

def do_cpu_intensive_calc():
print("Do smart calc...")
time.sleep(2) # blocking call. e.g. a spinning loop
print("Calc finished.")
return 2

await do_stuff()


Важно отметить, что задача с интенсивным использованием ЦП представлена ​​блокирующим спящим режимом, который нельзя дождаться, а задача, связанная с вводом-выводом, представлена ​​неблокирующим спящим режимом, который является ожидаемым. .

Это занимает 2,5 секунды на C# и 4,5 секунды на Python. Разница в том, что C# запускает асинхронный метод сразу, тогда как Python запускает метод только тогда, когда он достигает ожидания. Вывод ниже подтверждает это. Как мне добиться желаемого результата. Если это вообще возможно, мы будем признательны за код, который будет работать в Jupyter Notebook.

--- C# ---
Make API call...
Do smart calc...
Calc finished.
Data back.
The result is 3


--- Python ---
Do smart calc...
Calc finished.
Make API call...
Data back.
The result is 3




Обновление 1

Вдохновленное ответом knh190, оно кажется, что я могу пройти большую часть пути, используя asyncio.create_task(...). Это позволяет достичь желаемого результата (2,5 секунды): сначала запускается асинхронный код; далее блокирующий код ЦП выполняется синхронно; в-третьих, ожидается асинхронный код; наконец результаты объединяются. Чтобы асинхронный вызов действительно начал работать, мне пришлось добавить await asyncio.sleep(0), что выглядит как ужасный хак. Можем ли мы запустить задачу, не делая этого? Должен быть лучший способ...

async def do_stuff():
task = asyncio.create_task(do_iobound_work_async())
await asyncio.sleep(0) #

Подробнее здесь: https://stackoverflow.com/questions/562 ... wait-later
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»