Асинхронное программирование в Python Twisted - PullRequest
31 голосов
/ 17 сентября 2008

У меня проблемы с разработкой обратного прокси в Twisted. Это работает, но кажется слишком сложным и запутанным. Так много похоже на вуду.

Существуют ли простые, надежные примеры асинхронной структуры программы в Интернете или в книгах? Что-то вроде руководства по передовому опыту? Когда я закончу свою программу, я бы хотел как-то увидеть структуру, а не смотреть на миску спагетти.

Ответы [ 2 ]

64 голосов
/ 17 сентября 2008

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

Главное, что нужно иметь в виду, касательно Twisted или даже других асинхронных сетевых библиотек (таких как asyncore , MINA или ACE ), заключается в том, что Ваш код вызывается только тогда, когда что-то происходит. Часть, которую я слышал чаще всего, звучит как «вуду» - это управление обратными вызовами: например, Deferred. Если вы привыкли писать код, который выполняется по прямой линии и вызывает только те функции, которые сразу же возвращают результаты, идея ожидания того, что вам что-нибудь перезвонят, может сбить вас с толку. Но в колбэках нет ничего волшебного, никакого "вуду". На самом низком уровне реактор просто сидит и ждет, когда произойдет одно из небольшого числа событий:

  1. Данные поступают по соединению (он будет вызывать dataReceived по протоколу)
  2. Время прошло (будет вызываться функция, зарегистрированная с callLater).
  3. Соединение было принято (оно вызовет buildProtocol на заводе, зарегистрированном с помощью функции listenXXX или connectXXX).
  4. Соединение было разорвано (вызовет connectionLost по соответствующему протоколу)

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

Вот простой «движок, управляемый событиями», который показывает, насколько прост этот процесс.

# Engine
import time
class SimplestReactor(object):
    def __init__(self):
        self.events = []
        self.stopped = False

    def do(self, something):
        self.events.append(something)

    def run(self):
        while not self.stopped:
            time.sleep(0.1)
            if self.events:
                thisTurn = self.events.pop(0)
                thisTurn()

    def stop(self):
        self.stopped = True

reactor = SimplestReactor()

# Application    
def thing1():
    print 'Doing thing 1'
    reactor.do(thing2)
    reactor.do(thing3)

def thing2():
    print 'Doing thing 2'

def thing3():
    print 'Doing thing 3: and stopping'
    reactor.stop()

reactor.do(thing1)
print 'Running'
reactor.run()
print 'Done!'

В ядре таких библиотек, как Twisted, функция в главном цикле - это не sleep, а вызов операционной системы, такой как select() или poll(), представленный таким модулем, как модуль выбора Python. . Я говорю «нравится» select, потому что это API, который сильно различается между платформами, и почти каждый инструментарий GUI имеет свою версию. В настоящее время Twisted предоставляет абстрактный интерфейс для 14 различных вариантов этой темы. Обычная вещь, которую предоставляет такой API - это предоставить способ сказать: «Вот список событий, которые я жду. Идите спать, пока не произойдет одно из них, затем проснитесь и скажите мне, какое из них это было. «

1 голос
/ 17 сентября 2008

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

...