Функции Gevent не работают асинхронно
В этом уроке Gevent рассказывается, как создавать несколько потоков для асинхронной работы.
import gevent
import random
def task(pid):
"""
Some non-deterministic task
"""
gevent.sleep(random.randint(0,2)*0.001)
print('Task %s done' % pid)
def synchronous():
for i in range(1,10):
task(i)
def asynchronous():
threads = [gevent.spawn(task, i) for i in xrange(10)]
gevent.joinall(threads)
print('Synchronous:')
synchronous()
print('Asynchronous:')
asynchronous()
Результаты
Synchronous:
Task 1 done
Task 2 done
Task 3 done
Task 4 done
Task 5 done
Task 6 done
Task 7 done
Task 8 done
Task 9 done
Asynchronous:
Task 1 done
Task 5 done
Task 6 done
Task 2 done
Task 4 done
Task 7 done
Task 8 done
Task 9 done
Task 0 done
Task 3 done
Это работает, как я ожидал. Тем не менее, когда я заменяю тривиальную задачу сна на "рабочую" задачу, она не работает так же...
import gevent
import random
def task(pid):
start_time = time.time()
array = []
for x in range(0, 1000000):
x = str(x) + "WasteMyTime"
array.append(x)
elapsed_time = time.time() - start_time
print("Task " + str(pid) + " took " + str(elapsed_time))
def synchronous():
for i in range(1,10):
task(i)
def asynchronous():
threads = [gevent.spawn(task, i) for i in range(10)]
gevent.joinall(threads)
print('Synchronous:')
synchronous()
print('Asynchronous:')
asynchronous()
Результаты
Synchronous:
Task 1 took 0.3065943717956543
Task 2 took 0.2897024154663086
Task 3 took 0.29267001152038574
Task 4 took 0.2936718463897705
Task 5 took 0.28526878356933594
Task 6 took 0.29134082794189453
Task 7 took 0.28323960304260254
Task 8 took 0.28522467613220215
Task 9 took 0.28423142433166504
Asynchronous:
Task 0 took 0.2896885871887207
Task 1 took 0.2837369441986084
Task 2 took 0.28224802017211914
Task 3 took 0.2857201099395752
Task 4 took 0.28621697425842285
Task 5 took 0.28621697425842285
Task 6 took 0.28621602058410645
Task 7 took 0.2857208251953125
Task 8 took 0.28720879554748535
Task 9 took 0.2847275733947754
Каждая из асинхронных задач медленно распечатывается одна за другой, и весь асинхронный блок занимает столько же времени, сколько и синхронный блок. Это ошибка пользователя?
2 ответа
Добавьте это вверху вашего скрипта (1-я строка вашего скрипта)
from gevent import monkey; monkey.patch_all()
в основном используется для операций, связанных с вводом-выводом. Ваша задача связана с процессором. Одновременно может быть запущен только один гринлет.
Чтобы увидеть влияниеgevent
, вы должны выполнить задачу, связанную с вводом-выводом. Ниже приведен модифицированный пример, выполняющий сетевой запрос.
import time
import gevent
from gevent import monkey
monkey.patch_all()
import requests
def task(pid):
start_time = time.time()
requests.get('http://www.gstatic.com/generate_204')
elapsed_time = time.time() - start_time
print("Task " + str(pid) + " took " + str(elapsed_time))
def synchronous():
for i in range(1, 10):
task(i)
def asynchronous():
threads = [gevent.spawn(task, i) for i in range(10)]
gevent.joinall(threads)
print('Synchronous:')
synchronous()
print('Asynchronous:')
asynchronous()