2012-01-14 6 views
2

Я надеюсь на некоторое разъяснение по наилучшему способу обработки «первого» отложенных, то есть не просто добавить обратные вызовы и ошибки к существующим витым методам, которые возвращают отложенный, но лучший способ от создания оригинал отложенные.Python Twisted Отложенные: требуется уточнение

В качестве конкретного примера, вот 2 вариации одного и того же метода: он просто подсчитывает количество строк в некоторых довольно больших текстовых файлов, а также используется в качестве отправной точки для цепи deferreds.

Метод 1: Это один не чувствует себя так хорошо, как отложенный обжигают непосредственно методом reactor.callLater.

def get_line_count(self): 
    deferred = defer.Deferred() 

    def count_lines(result): 
     try: 
      print_file = file(self.print_file_path, "r") 
      self.line_count = sum(1 for line in print_file) 
      print_file.close() 
      return self.line_count 
     except Exception as inst: 
      raise InvalidFile() 

    deferred.addCallback(count_lines) 
    reactor.callLater(1, deferred.callback, None) 
    return deferred 

Метод 2: немного лучше, так как отложенный фактически уволен когда результат доступен

def get_line_count(self): 
    deferred = defer.Deferred() 

    def count_lines(): 
     try: 
      print_file = file(self.print_file_path, "r") 
      self.line_count = sum(1 for line in print_file) 
      print_file.close() 
      deferred.callback(self.line_count) 
     except Exception as inst: 
      deferred.errback(InvalidFile()) 

    reactor.callLater(1, count_lines) 
    return deferred 

Примечание: Можно также отметить, что оба эти фактически синхронные и потенциально блокирующие методы (и я, возможно, мог бы использовать «MaybeDeferred»?). Но хорошо, что это на самом деле один из аспектов, с которыми я запутался.

  1. Для Способ 2, если count_lines метод очень медленно (считая строки в некоторых больших файлов и т.д.), это будет потенциально «блок» в целом Twisted приложение? Я прочитал довольно много документации о том, как обратные вызовы и ошибки и реактор ведут себя вместе (обратные вызовы должны выполняться быстро или возвращать отложенные сами и т. Д.), Но в этом случае я просто не вижу и действительно ценю некоторые указатели/примеры и т.д.

  2. есть некоторые статьи/четких объяснения, которые имеют дело с наилучшим подходом к созданию этого «первое» deferreds? Я прочитал these excellent articles, и они очень помогли с некоторым из основных понятий, но я все еще чувствую, что мне не хватает части.

  3. Для блокировки кода, это было бы это typicall случае DeferToThread или reactor.spawnprocess? Я прочитал много вопросов, как this one и this article, но я до сих пор не 100% уверен в том, как иметь дело с потенциально блокирующий код, в основном при работе с файлом ввода/вывода

К сожалению, если все это кажется слишком основным, но я действительно хочу, чтобы повесить использование Twisted более тщательно. (Это был действительно мощный инструмент для всех сетевых аспектов). Спасибо за ваше время!

ответ

2

Да, у вас все в порядке: вам нужны потоки или отдельные процессы, чтобы избежать блокировки цикла Twisted. Использование «Отложенные» не заставит ваш код не блокировать.Для ваших вопросов:

  1. Да, вы бы блокировать цикл событий, если count_lines очень медленно. Отложив его на поток, вы решите это.

  2. Я использовал Twisteds documentation, чтобы узнать, как работают Отсрочки, но я думаю, вы уже прошли через это. Статья о database support была информацией, поскольку в ней четко сказано, что эта библиотека построена с использованием потоков. Вот как вы соединяете синхронно-асинхронный разрыв.

  3. Если звонок действительно блокируется, вам необходимо указать DeferToThread. Сам Python является своеобразным однопоточным, что означает, что только один поток может выполнять байт-код Python за раз. Тем не менее, если создаваемый поток будет блокироваться на вводе-выводе, то эта модель отлично работает: поток освободит блокировку глобального интерпретатора и, таким образом, позволит запускать другие потоки Python, включая основной поток с циклом цикла Twisted.

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

Я надеюсь, что это станет еще более ясным!

+0

Большое спасибо за быстрый и тщательный ответ, Мартин! 1. и 2. Хорошо, подход Thread/Threadpool * делает * смысл в этом случае. –

+0

3. Я склонен относиться с осторожностью к потокам в Python из-за GIL, но обычно это ** должно ** быть в состоянии справиться с 3-мя потоками, использующими методы 'count_lines' примерно в одно и то же время, не запутывая событие Twisted (метод используется в небольших «задачах», которые затем отправляют данные из файлов на устройства через последовательный порт) –

+0

Спасибо за информацию о выбранном модуле, похоже, «связан» с различными типами реакторов в Twisted. Я рассмотрю его более подробно! Для практического использования, к сожалению, он поддерживает только сокеты на платформах Windows (отсюда довольно странные ограничения, которые я имел при использовании скрученной последовательной поддержки в Windows). –

Смежные вопросы