2016-01-31 5 views
15

Недавно я погружался в Twisted docs. Из того, что я собрал, основой функциональности Twisted является результат его цикла событий, называемого «Реактор». Реактор прослушивает определенные события и отправляет их зарегистрированным функциям обратного вызова, которые были разработаны для обработки этих событий. В книге есть некоторый псевдокод, описывающий, что делает Реактор, но у меня проблемы с пониманием этого, это просто не имеет никакого смысла для меня.Как работает Twisted Reactor от Python?

while True: 
    timeout = time_until_next_timed_event() 
    events = wait_for_events(timeout) 
    events += timed_events_until(now()) 
    for event in events: 
     event.process() 

Что это значит?

ответ

25

В случае, если это не очевидно, это называется реактор, потому что он реагирует на вещи. Цикл как реагирует.

Одна линия на время:

while True: 

Это не фактическиwhile True; это больше похоже на while not loop.stopped. Вы можете позвонить reactor.stop(), чтобы остановить цикл, и (после выполнения некоторой логики отключения) цикл будет фактически завершен. Но это изображается в примере как while True, потому что, когда вы пишете долгоживущую программу (как часто вы с Twisted), лучше предположить, что ваша программа будет либо сбой или запуск навсегда, и что «чистое выход» не действительно вариант.

 timeout = time_until_next_timed_event() 

Если бы мы должны были расширить этот расчет немного, это может сделать больше смысла:

def time_until_next_timed_event(): 
    now = time.time() 
    timed_events.sort(key=lambda event: event.desired_time) 
    soonest_event = timed_events[0] 
    return soonest_event.desired_time - now 

timed_events список мероприятий, запланированных с reactor.callLater; то есть функции, которые приложение попросило Twisted для запуска в определенное время.

 events = wait_for_events(timeout) 

Эта линия представляет собой «магическую» часть витой пары. Я не могу расширить wait_for_events в общем виде, потому что его реализация зависит от того, как операционная система делает нужные события доступными. И, учитывая, что операционные системы являются сложными и хитрыми зверями, я не могу расширять его определенным образом, сохраняя при этом достаточно простым для ответа на ваш вопрос.

Эта функция предназначена для обозначения того, спросите операционную систему или оболочку Python вокруг нее блокировать до тех пор, пока один или несколько объектов, ранее зарегистрированных с ней, - как минимум, такие, как порты прослушивания и установленные соединения, но также, возможно, такие вещи, как кнопки, на которые можно щелкнуть - «готов к работе». Работа может считывать некоторые байты из сокета, когда они поступают из сети. Работа может записывать байты в сеть, когда буфер опустошается достаточно для этого. Это может быть прием нового соединения или использование закрытого. Каждое из этих возможных событий - это функции, которые реактор может потребовать от ваших объектов: dataReceived, buildProtocol, resumeProducing и т. Д., Что вы узнаете, пройдете ли вы полный учебник Twisted.

После того, как у нас есть список гипотетических объектов «события», каждый из которых имеет воображаемый метод «process» (точные названия методов в реакторе отличаются только из-за несчастных случаев истории), мы тогда вернуться к работе со временем:

 events += timed_events_until(now()) 

Во-первых, это предполагает, events просто list абстрактного Event класса, который имеет process метод, что каждый конкретный тип события, необходимо заполнить.

На этом этапе цикл «проснулся», потому что wait_for_events, остановил блокировку. Тем не менее, мы не знаем, сколько запланированных событий мы могли бы выполнить на основе , как долго он «заснул» для. Возможно, мы спали за полный тайм-аут, если ничего не было, но если бы было много соединений, мы могли бы спать практически без времени. Поэтому мы проверяем текущее время («now()»), и мы добавляем в список событий, которые нам нужно обработать, каждое событие с таймером с desired_time, которое находится в или до настоящего времени.

Наконец,

 for event in events: 
     event.process() 

Это просто означает, что Twisted просматривает список вещей, которые он должен делать, и делает их. В действительности, конечно, он обрабатывает исключения вокруг каждого события, и конкретная реализация реактора часто просто обращается прямо к обработчику событий, а не создает объект, похожий на Event, для записи работы, которая должна быть выполнена в первую очередь, но концептуально это просто что происходит. event.process здесь может означать вызов socket.recv(), а затем yourProtocol.dataReceived с результатом, например.

Надеюсь, что это расширенное объяснение поможет вам обвести вокруг себя голову. Если вы хотите узнать больше о Twisted, работая над этим, я бы посоветовал вам join the mailing list, перескочить на канал IRC, #twisted, чтобы поговорить о приложениях или #twisted-dev, чтобы работать на самом скрученном, как на Freenode.

2

Постараюсь подробно:

  • Программа управления дает и пойти спать на ожидании событий. Я предполагаю, что самая интересная часть здесь - событие. Событие: по внешнему запросу (получение сетевого пакета, щелчок по клавиатуре, таймер, другой программный вызов) программа получает управление (в какой-то другой поток или в специальной рутине). Как-то сон в wait_for_events прерван и wait_for_events возвращается.

  • На что появление контроля обработчик событий хранит информацию об этом событии в некоторую структуру данных, событий, который впоследствии используется для делать что-то о том, что событий (событийно> процесса). Может произойти не только одно, но и много событий за время между входом и выходом wait_for_events, все они должны быть обработаны. event-> process() процедура обычная и обычно должна называть интересную часть - витой код пользователя.