Чистая, легкая альтернатива витой Python? [закрыто]

222

(Давным-давно) я написал веб-паук, который я многопоточный для одновременного выполнения запросов. Это было в моей юности Python, в те дни, когда я знал о GIL и связанных с ним проблемах, которые он создает для многопоточного кода (IE, в большинстве случаев, все просто заканчивается сериализацией!) ...

Я хотел бы переработать этот код, чтобы сделать его более надежным и работать лучше. В принципе, я мог бы сделать это двумя способами: я мог бы использовать новый многопроцессорный модуль в версии 2.6+ или использовать модель, основанную на реакторах / событиях. Я бы предпочел сделать позже, так как это намного проще и менее подвержено ошибкам.

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

  • Twisted : дедушка Python каркас реактора: кажется сложным и немного раздутым, однако. Крутая кривая обучения для небольшой задачи.
  • Eventlet : От парней из Lindenlab . Фреймворк на основе Greenlet, предназначенный для решения подобных задач. Хотя я взглянул на код, и он не слишком красивый: не соответствует pep8, разбросан по принтам (почему люди делают это в рамках !?), API кажется немного непоследовательным.
  • PyEv : Незрелый, похоже, никто не использует его сейчас, хотя он основан на libevent, поэтому у него есть солидный бэкэнд.
  • asyncore : из stdlib: über low-level, кажется, что нужно приложить много усилий, чтобы просто что-то поднять.
  • tornado : Хотя это серверный продукт, предназначенный для динамических веб-сайтов, в нем есть асинхронный HTTP-клиент и простой ioloop . Похоже, что это может сделать работу, но не то, для чего она была предназначена. [править: к сожалению, не работает в Windows, что для меня важно - это требование для меня, чтобы поддерживать эту слабую платформу]

Я что-то пропустил? Конечно, должна существовать библиотека, которая подходит для сладкой асинхронной сетевой библиотеки!

[edit: большое спасибо intgr за указатель на эту страницу . Если вы прокрутите вниз, то увидите, что есть действительно хороший список проектов, которые нацелены на то или иное решение этой задачи. Похоже, что с момента появления Twisted все действительно пошло дальше: теперь люди предпочитают решение, основанное на совместной рутине, а не традиционное решение, ориентированное на реактор / обратный вызов. Преимущества этого подхода заключаются в более четком и понятном коде: я наверняка обнаружил это в прошлом, особенно при работе с boost.asio.в C ++ этот код, основанный на обратном вызове, может привести к проектам, которые могут быть трудны для понимания и относительно неясны для неопытного глаза. Использование сопрограмм позволяет вам писать код, который выглядит как минимум немного более синхронным. Думаю, теперь моя задача - выяснить, какая из этих многочисленных библиотек мне нравится, и попробовать! Рад, что спросил сейчас ...]

[править: возможно, представляет интерес для тех, кто следил или наткнулся на этот вопрос или в какой-то мере интересуется этой темой: я нашел действительно отличную рецензию на текущее состояние доступных инструментов для этой работы]

JKP
источник
14
Python является многопоточным, он просто не позволяет двум потокам выполнять код Python одновременно.
интегрирования
86
Я узнал намного больше из вашего вопроса, чем из ответов на него.
Денис Откидач
2
@Denis: хе, спасибо, наверное! В ответах также было несколько хороших указателей, особенно intgr. Я знал о множестве вариантов, и я не просто хотел, чтобы ответы были упакованы с ними, поэтому я решил изо всех сил
изложить
5
> Сейчас люди, похоже, предпочитают решение, основанное на совместной рутине, а не традиционное решение, ориентированное на реактор / обратный вызов. «решения, основанные на совместной рутине» и «решения, ориентированные на реактор», являются ортогональными (Не обращая внимания на тот факт, что в Python нет сопрограмм) Посмотрите на inlineCallbacks Twisted, чтобы увидеть, как вы можете иметь стиль программирования, который вы предпочитаете, с надежным, зрелым сетевым уровнем, который не собирается подвергать вас сложным идиосинкразиям платформы.
Жан-Поль Кальдероне
2
Несколько моментов, которые нужно добавить: 1. Tornado отлично работает на Windows. Это просто не так эффективно и масштабируемо, потому что используется selectдля мультиплексирования ввода / вывода. Но вы должны быть в состоянии получить достойную производительность из этого с торнадо-пьюв . 2. В Python 3.3+ и его троллее backport теперь есть asyncio, который позволяет запускать любое приложение Tornado в цикле событий (Twisted будет поддерживаться в ближайшее время).
schlamar

Ответы:

28

Мне понравился модуль Python для параллелизма, который использует микропотоки Stackless Python или Greenlets для облегчения потоков. Все блокирующие сетевые операции ввода / вывода прозрачно делаются асинхронными через один libeventцикл, поэтому он должен быть почти таким же эффективным, как настоящий асинхронный сервер.

Я предполагаю, что это похоже на Eventlet таким образом.

Недостатком является то, что его API сильно отличается от модулей sockets/ Python threading; вам нужно переписать значительную часть вашего приложения (или написать слой совместимости совместимости)

Редактировать: Кажется, что есть также Cogen , который похож, но использует расширенные генераторы Python 2.5 для своих сопрограмм, а не Greenlets. Это делает его более портативным, чем совпадение и другие альтернативы. Сетевой ввод-вывод выполняется напрямую с помощью epoll / kqueue / iocp.

время интегрирования
источник
@intgr: отличные ссылки. Я видел оба из них раньше, это те вещи, которые я надеялся увидеть вспыхнувшими. +1
jkp
3
Похоже, совпадение - это мертвый проект с последним обновлением четыре года назад.
Gewthen
проект мертв, как и Hyves!
Бахадир Камбел
1
Многое произошло с Python 2.5. Asyncio в Python 3.5 это здорово.
Джозеф Шиди
99

Скручивать сложно, вы правы в этом. Витая не раздутая.

Если вы посмотрите здесь: http://twistedmatrix.com/trac/browser/trunk/twisted вы найдете организованный, всеобъемлющий и очень хорошо протестированный набор многих протоколов Интернета, а также вспомогательный код для написания и развертывать очень сложные сетевые приложения. Я бы не перепутал раздувание со всесторонностью.

Хорошо известно, что документация Twisted не является самой удобной с первого взгляда, и я считаю, что это отвлекает несчастное количество людей. Но Twisted это удивительно (ИМХО), если вы вкладываете время. Я сделал, и это оказалось того, и я бы порекомендовал другим попробовать то же самое.

clemesha
источник
4
@clemesha: может быть, вы правы, и это не обманывают, но кажется, что слишком много, чтобы заставить мою голову сделать что-то простое. Я понимаю асинхронное программирование, я работал на C ++ с boost :: asio, так что концепции не новы, но это вся сущность, которая подходит для создания извращенных вещей: это совершенно новый мир, очень похожий на django для веб-материалов. Опять же, когда я занимаюсь веб-вещанием, я работаю с легким кодом WSGI и объединяю только то, что мне нужно. Лошади для курсов, я думаю.
JKP
7
@clemesha: эм, я сегодня сделал решительный шаг, чтобы взглянуть: витая весит 20 МБ! Даже ядро ​​12MB .... если это не раздуто, я не совсем уверен, что это такое.
JKP
29
Базовые API Twisted довольно малы (реактор, отложенный, протокол). Большая часть кода Twisted представляет собой реализации асинхронного протокола, использующие эти основы. «Раздувание» не является полезным прилагательным здесь (или, действительно, в большинстве случаев). Размер Twisted является разумным для количества вещей, которые он делает.
daf
56

gevent - это очищенный eventlet .

API-интерфейс следует тем же соглашениям, что и стандартная библиотека (в частности, многопоточные и многопроцессорные модули), где это имеет смысл. Таким образом, у вас есть знакомые вещи, такие как Очередь и Событие, с которыми можно работать.

Он поддерживает только libevent ( update: libev начиная с 1.0 ) в качестве реализации реактора, но в полной мере использует его, предоставляя быстрый WSGI-сервер на основе libevent-http и разрешая DNS-запросы через libevent-dns, в отличие от использования пула потоков, как и большинство других библиотек. делать. ( обновление: начиная с 1.0 c-ares используется для выполнения асинхронных DNS-запросов; также возможен пул потоков).

Как и eventlet, он делает обратные вызовы и отложенные ссылки ненужными с помощью гринлетов .

Посмотрите примеры: одновременная загрузка нескольких URL , длинный опрос в чате .

Денис Биленко
источник
4
Я буду вторым gevent - после рассмотрения многих решений, gevent работал очень хорошо для меня. Это позволило мне сохранить лучшую часть моей существующей программы, и требуемые изменения были тривиальными - лучше всего, если код необходимо поддерживать через 3, 4, 5, ... года, он все еще делает смысл для тех, кто не знаком с gevent, самый большой демонстрационный шаг для Twisted - это сильная кривая обучения, это вызывает проблемы не только при реализации, но и дальше в процессе обслуживания ...
Martin Tournoij
27

Очень интересное сравнение таких фреймворков было составлено Николасом Пиелем в его блоге: его стоит прочитать!

JKP
источник
2
Хотя я согласен с тем, что статья была интересной, я думаю, что стоит рассмотреть обоснованность представленных тестов. Смотрите комментарии здесь: reddit.com/r/programming/comments/ahepg/…
clemesha
1
@clemesha, хотя на этой странице reddit стоит отметить точку отсчета, тест был выполнен на двухъядерной машине и, вероятно, не страдал описанным фатальным недостатком. Я полагаю , что это возможно , и клиент , и сервер побежал на том же ядре, но это не кажется вероятным.
Питер Хансен
15

Ни одно из этих решений не избежит того факта, что GIL предотвращает параллелизм ЦП - это всего лишь лучший способ получить параллелизм ввода-вывода, который у вас уже есть с потоками. Если вы считаете, что можете улучшить IO, обязательно выполните одно из этих действий, но если ваше узкое место заключается в обработке результатов, здесь ничего не поможет, кроме модуля многопроцессорной обработки.

Адам Хупп
источник
Что не так с использованием нескольких процессов?
Эмиль Иванов
3
Совсем ничего, отсюда и предложение использовать многопроцессорный модуль.
Адам Хапп
11

Я бы не пошел так далеко, чтобы назвать Twisted раздутым, но трудно обернуть голову вокруг. Я довольно долго избегал действительно учиться, потому что всегда хотел чего-то более легкого для «небольших задач».

Тем не менее, теперь, когда я поработал с ним еще немного, я должен сказать, что все батареи в комплекте ОЧЕНЬ приятно.

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

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

rhettg
источник
Если вы когда-нибудь посмотрели, как реализован реактор gtk под Windows (хардкорный опрос каждые 10 мс: twistedmatrix.com/trac/browser/trunk/twisted/internet/… ), вы бы не назвали это «зрелым» ...
schlamar
2
Привет @ Schlamar. Этот неприятный хак был реализован как обходной путь для некоторых довольно серьезных ошибок в GTK +, еще в то время, когда было гораздо меньше забот о энергоэффективности :). Но прелесть Twisted в том, что мы можем однажды исправить эту ошибку , исправить ее в фреймворке, и нашим пользователям не нужно беспокоиться об этом. Хотели бы вы внести исправление, которое решает эту проблему и избавляется от нее (осуждает, а затем удаляет) PortableGtkReactor?
Глиф
1
@Glyph Я добавил полезный совет по адресу twistedmatrix.com/trac/ticket/4744#comment:2, если кто-то еще хочет решить эту проблему, потому что некоторые из этих проблем все еще существуют. Кстати, вы могли бы решить эту проблему гораздо эффективнее, запланировав обратные вызовы между двумя циклами событий.
schlamar
7

Камаэлия еще не упоминалась. Его модель параллелизма основана на соединении компонентов с передачей сообщений между входящими и исходящими сообщениями. Вот краткий обзор.

Стивен Крыскалла
источник
5
Я использовал kamaelia для приложения - это было очень больно. ИМХО есть и другие, более лучшие варианты для одновременного использования в python (большинство из которых упомянуты выше)
Бен Форд
7

Я начал использовать витой для некоторых вещей. Его красота почти в том, что он «раздутый». Существуют разъемы практически для любых основных протоколов. У вас может быть jabber-бот, который будет принимать команды и публиковать их на irc-сервере, отправлять их кому-либо по электронной почте, запускать команды, читать с NNTP-сервера и отслеживать изменения на веб-странице. Плохая новость в том, что он может делать все это и может слишком усложнять выполнение простых задач, таких как объяснение ОП. Преимущество Python в том, что вы включаете только то, что вам нужно. Таким образом, хотя загрузка может быть 20 МБ, вы можете включить только 2 МБ библиотек (что все еще много). Моя самая большая претензия к Twisted заключается в том, что они включают примеры, что угодно, кроме базового tcp-сервера, который вы можете использовать самостоятельно.

Хотя я и не являюсь решением на python, я видел, что node.js в последнее время набирает обороты На самом деле, я подумывал о том, чтобы изучить его для небольших проектов, но я просто съеживаюсь, когда слышу javascript :)

vrillusions
источник
Я большой поклонник Python. - Проверьте «Javascript - хорошие части» от Дугласа Крокфорда (3, 4 видео). И взглянуть на CoffeeScript. Оказывается, в JS есть вещи, которые должен иметь Python, кроме синтаксиса, хаха. CS пытался смягчить это, но немного неуклюже в этом ...
Роберт Симер
4

На эту тему есть хорошая книга Абэ Феттига "Основы программирования для витой сети". Примеры показывают, как писать очень Pythonic-код, и лично мне, не кажется мне основанным на раздутой структуре. Посмотрите на решения в книге, если они не чистые, тогда я не знаю, что такое чистый.

Моя единственная загадка такая же, как и у других фреймворков, таких как Ruby. Я волнуюсь, это масштабируется? Я бы не хотел привязывать клиента к среде, которая будет иметь проблемы с масштабируемостью.

mrsmoothie
источник
4

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

bfrog
источник
2

Также попробуйте Syncless . Он основан на сопрограммах (поэтому он похож на Concurrence, Eventlet и gevent). Он реализует вставные неблокирующие замены для socket.socket, socket.gethostbyname (и т. Д.), Ssl.SSLSocket, time.sleep и select.select. Это быстро. Для этого нужен Stackless Python и libevent. Он содержит обязательное расширение Python, написанное на C (Pyrex / Cython).

PTS
источник
2

Подтверждаю доброту syncless . Он может использовать libev (более новая, более чистая и более производительная версия libevent). Некоторое время назад у него не было такой поддержки, как у libevent, но теперь процесс разработки идет дальше и очень полезен.

Роберт Заремба
источник
1

Если вам нужна упрощенная и легкая библиотека HTTP-запросов, тогда я нахожу Unirest действительно хорошим

ejectamenta
источник
0

Вы можете взглянуть на PyWorks, который использует совершенно другой подход. Он позволяет экземплярам объекта работать в своем собственном потоке и вызывает функции для этого объекта асинхронно.

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

res = obj.method( args )
# code continues here without waiting for method to finish
do_something_else( )
print "Result = %d" % res # Code will block here, if res not calculated yet

PyWorks можно найти на http://bitbucket.org/raindog/pyworks

renejsum
источник
1
Хотя это интересно и может подойти для некоторых задач, использование потоков для работы в сети плохо (особенно на Python из-за GIL). И это был как раз вопрос: четная структура или многопроцессорная обработка. Так что ваш ответ явно выходит за рамки ...
schlamar