Чистая, легкая альтернатива извращенному Python?

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

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

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

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

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

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

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


person jkp    schedule 01.12.2009    source источник
comment
Python является многопоточным, он просто не позволяет двум потокам одновременно выполнять код Python.   -  person intgr    schedule 01.12.2009
comment
@Intgr: действительно так, поэтому теоретически, поскольку socket является модулем C, если они позволяют GIL работать до вызова базовой процедуры, все может быть на самом деле параллельным. Тем не менее, я думаю, что хочу вернуться к чему-то однопоточному.   -  person jkp    schedule 01.12.2009
comment
Я узнал гораздо больше из вашего вопроса, чем из ответов на него.   -  person Denis Otkidach    schedule 01.12.2009
comment
@Денис: хех, спасибо, наверное! В ответах также было несколько хороших указателей, особенно intgr. Я знал о многих вариантах, и я не просто хотел, чтобы ответы были заполнены ими, поэтому я подумал, что постараюсь изложить то, что я знал :)   -  person jkp    schedule 01.12.2009
comment
› кажется, что теперь люди предпочитают решение, основанное на сопрограммах, а не традиционное решение, ориентированное на реактор/обратный вызов. Это неразумное сравнение. решения, основанные на сопрограммах, и решения, ориентированные на реактор, ортогональны. (Игнорируя тот факт, что Python не имеет сопрограмм). Взгляните на inlineCallbacks Twisted, чтобы увидеть, как вы можете использовать стиль программирования, который вы предпочитаете, с надежным, зрелым сетевым уровнем, который не будет подвергать вас сложным особенностям платформы.   -  person Jean-Paul Calderone    schedule 01.12.2009
comment
@ Жан-Поль Кальдероне: Хорошо, я посмотрю на inlineCallbacks, которые для меня новы. Как я уже говорил, у Twisted есть крутая кривая обучения. С чего мне начать для небольшой задачи, которую я хочу выполнить? В любом случае, я думаю, почему некоторые люди считают сопрограммы хорошей альтернативой, резюмировано здесь: weightless.io/background но вы правы: я уверен, что любая из реализаций сопрограммы для Python теоретически может быть использована с Twisted. И да, Python не поддерживает сопрограммы из коробки, но вы можете легко их добавить.   -  person jkp    schedule 01.12.2009
comment
@Jean-Paul Calderone: вы можете реализовать сопрограммы на простом Python, используя функции генератора (да, это хак, но они все еще сопрограммы).   -  person intgr    schedule 01.12.2009
comment
Я не понимаю Твистед. Кажется, он хочет реализовать каждый протокол в мире, о да, и хочет работать с любым циклом событий в мире без его настройки пользователем (GTK и т. д.). Было бы неплохо, если бы было что-то асинхронное, которое просто позволяло бы вам складывать протоколы так, как вы хотите.   -  person L̲̳o̲̳̳n̲̳̳g̲̳̳p̲̳o&#x    schedule 28.04.2010
comment
@Longpoke: Twisted является чем-то асинхронным, что позволяет вам складывать протоколы так, как вы хотите :). Среди прочего, я говорил о том, насколько он легкий. См. здесь pycon.tv/#/video/58.   -  person Glyph    schedule 31.03.2011
comment
Есть ли шанс обновить этот вопрос и / или ответы, чтобы отразить текущее состояние дел?   -  person blueberryfields    schedule 08.11.2013
comment
Несколько моментов, которые следует добавить: 1. Tornado очень хорошо работает на Windows. Просто он не такой производительный и масштабируемый, потому что использует select для мультиплексирования ввода/вывода. Но вы сможете добиться приличной производительности с помощью tornado-pyuv. 2. Теперь в Python 3.3+ есть asyncio и его бэкпорт trollius, который позволяет запускать любое приложение Tornado в его цикл обработки событий (скоро будет поддерживаться Twisted).   -  person schlamar    schedule 17.01.2014


Ответы (14)


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

Я полагаю, что в этом он похож на Eventlet.

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

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

person intgr    schedule 01.12.2009
comment
@intgr: отличные ссылки. Я видел оба из них раньше однажды, это те вещи, которые я надеялся увидеть вспыхнувшими. +1 - person jkp; 01.12.2009
comment
Похоже, concurrence — это мертвый проект, последнее обновление которого было выпущено четыре года назад. - person Gewthen; 12.07.2013
comment
проект мертв, как и Hyves! - person Bahadir Cambel; 24.01.2014
comment
Многое произошло со времен Python 2.5. asyncio в Python 3.5 великолепен. - person Joseph Sheedy; 01.11.2016

Twisted сложен, в этом ты прав. Twisted не раздут.

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

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

person clemesha    schedule 01.12.2009
comment
@clemesha: может быть, вы правы, и он не загружен, но мне кажется, что слишком много всего, чтобы заставить себя сделать что-то простое. Я разбираюсь в асинхронном программировании, я работал на C++ с boost::asio, так что концепции не новы, но это вся болтовня, которая конкурирует с извращенными вещами: это совершенно новый мир, очень похожий на django для веб-материалов. Опять же, когда я делаю веб-материалы, я работаю с облегченным кодом WSGI и подключаю только то, что мне нужно. Лошади для курсов, я думаю. - person jkp; 01.12.2009
comment
@clemesha: эм, сегодня я рискнул посмотреть: скрученный весит 20 МБ! Даже ядро ​​​​12 МБ .... если оно не раздуто, я не совсем уверен, что это такое. - person jkp; 07.12.2009
comment
Базовые API Twisted довольно малы (реактор, отложенный, протокол). Большая часть кода Twisted представляет собой реализацию асинхронного протокола, использующую эти основы. Раздувание здесь неуместное прилагательное (да и в большинстве случаев). Размер Twisted разумен для того количества вещей, которые он делает. - person daf; 14.12.2009

gevent очистка событий.

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

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

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

Ознакомьтесь с примерами: одновременная загрузка нескольких URL-адресов, < href="http://blog.gevent.org/2009/10/10/simpler-long-polling-with-django-and-gevent/" rel="nofollow noreferrer">веб-чат с длинным опросом.

person Denis Bilenko    schedule 02.12.2009
comment
Я буду вторым gevent. После просмотра многих решений gevent сработал для меня очень хорошо. Это позволило мне сохранить лучшую часть моей существующей программы, а необходимые изменения были тривиальными. Лучше всего то, что если код нужно поддерживать через 3, 4, 5, ... лет, он все еще делает смысл для тех, кто не знаком с gevent, самый большой показатель для Twisted — это сильная кривая обучения, это вызывает проблемы не только при реализации, но и в дальнейшем во время обслуживания... - person Martin Tournoij; 16.09.2011

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

person jkp    schedule 23.12.2009
comment
Хотя я согласен с тем, что статья была интересной для чтения, я думаю, что стоит рассмотреть достоверность представленных тестов. См. комментарии здесь: reddit.com/r/programming/comments/ahepg/ - person clemesha; 27.12.2009
comment
@clemesha, хотя на этой странице Reddit стоит отметить, что тест проводился на двухъядерной машине и, вероятно, не страдал описанным фатальным недостатком. Я полагаю, что возможно и клиент, и сервер работали на одном ядре, но это маловероятно. - person Peter Hansen; 13.03.2010

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

person Adam Hupp    schedule 01.12.2009
comment
Что плохого в использовании нескольких процессов? - person Emil Ivanov; 16.01.2010
comment
Вообще ничего, отсюда и предложение использовать многопроцессорный модуль. - person Adam Hupp; 16.03.2010

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

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

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

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

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

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

person Steven Kryskalla    schedule 01.12.2009
comment
Я использовал kamaelia для приложения - это было очень больно. ИМХО, есть и другие, лучшие варианты concurrenct в python (большинство из которых упомянуты выше) - person Ben Ford; 14.10.2010

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

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

person vrillusions    schedule 23.07.2010
comment
Я большой поклонник Python. – Посмотрите «Javascript – The good parts» от Дугласа Крокфорда (видео 3, 4). И загляните в CoffeeScript. Оказывается, в JS есть то, что должно быть в Python, кроме синтаксиса, ха-ха. CS пытался смягчить это, но немного неуклюж в этом... - person Robert Siemer; 09.11.2013

На эту тему есть хорошая книга: «Основы программирования Twisted Network» Эйба Феттига. Примеры показывают, как писать очень питонический код, и лично мне не кажется, что он основан на раздутом фреймворке. Посмотрите на решения в книге, если они не чистые, то я не знаю, что значит чистый.

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

person mrsmoothie    schedule 26.02.2010

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

person bfrog    schedule 13.09.2010

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

person pts    schedule 19.04.2010

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

person Robert Zaremba    schedule 16.01.2011

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

person ejectamenta    schedule 21.01.2015

Вы можете взглянуть на 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.

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