Появление функций асинхронно с использованием Gevents - PullRequest
5 голосов
/ 07 февраля 2012

Я проходил Gevents (библиотеку python для функциональности asych) и написал очень маленькую программу, чтобы понять, как она работает, но результаты были довольно непонятными. Ниже приведен код

import gevent 
import time 


def mytime(t):
    time.sleep(t)
    print " i have slept for ",t,"secs"

x = range (0,10)
x.reverse()

for i in x :
    jobs = [ gevent.spawn(mytime , i) ] 
gevent.joinall(jobs)

Вывод, независимо от того, сколько раз я бегу, я получаю

 i have slept for  9 secs
 i have slept for  8 secs
 i have slept for  7 secs
 i have slept for  6 secs
 i have slept for  5 secs
 i have slept for  4 secs
 i have slept for  3 secs
 i have slept for  2 secs
 i have slept for  1 secs
 i have slept for  0 secs

Существует аналогичный пример, представленный в виде части учебника gevent .

, где функциональность асинхронности довольно очевидна. Все, что я сделал, это добавил функциональность сна в код. не должно ли быть что-то подобное? ??

     i have slept for  6 secs
     i have slept for  8 secs
     i have slept for  5 secs
     i have slept for  9 secs
     i have slept for  7 secs
     i have slept for  0 secs
     i have slept for  3 secs
     i have slept for  2 secs
     i have slept for  1 secs
     i have slept for  4 secs

Ответы [ 2 ]

9 голосов
/ 07 февраля 2012

Ваша реакция на урок, кажется, показывает, что вы пропустили часть того, что он пытается показать.

В асинхронной части кода урока основная причина, по которой задачи завершаются в случайном порядкепотому что они спали в течение случайного периода времени .

Они все еще спят в течение произвольного периода времени в синхронной части кода, но потому чтокаждая задача выполняется после того, как предыдущая закончилась, они также заканчиваются в этом последовательном порядке.

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

Наконец, если вы соблюдаете наблюдательность, вы заметите, что они заканчивают в обратном порядке, как вы могли бы ожидать.

Почему это так?

Поскольку вы вставили блокирующий код в ваш пример.Код блокировки time.sleep().Когда что-то блокируется, это означает, что оно перехватило все выполнение для себя и больше не будет запускать ничего (например, другие ваши гринлеты) до тех пор, пока оно не завершится.

Так как это единственная «работа», котораякаждая функция делает ваш код снова синхронным.

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

Gevent предоставляет неблокирующую версию time.sleep() - gevent.sleep().Вы заметите, что это то, что используется в учебном коде.Вы также можете патч обезьяны эту функцию.На данный момент вы обычно предпочитаете просто использовать версию Gevent.

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

edit: у вас также есть неверная логика в цикле создания задания.

лучше -

jobs = []
for i in x:
    jobs.append(gevent.spawn(mytime, i))

или, проще, просто:

jobs = [gevent.spawn(mytime, i) for i in x]
4 голосов
/ 07 февраля 2012

Вы должны использовать gevent.sleep() вместо time.sleep(), чтобы получить правильный вывод:

import gevent

def mytime(t):
    gevent.sleep(t) #NOTE: not time.sleep()
    print " i have slept for ",t,"secs"

jobs = [gevent.spawn(mytime, i) for i in reversed(range(10))]
gevent.joinall(jobs)

выход

 i have slept for  0 secs
 i have slept for  1 secs
 i have slept for  2 secs
 i have slept for  3 secs
 i have slept for  4 secs
 i have slept for  5 secs
 i have slept for  6 secs
 i have slept for  7 secs
 i have slept for  8 secs
 i have slept for  9 secs

Чем больше i, тем позже mytime(i) производит вывод независимо от порядка mytime(i).

Вы можете использовать time.sleep(), если сначала установите обезьяну:

import gevent.monkey
gevent.monkey.patch_time()

import time
...