Чистая, легкая альтернатива витой 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 ++ этот код, основанный на обратном вызове, может привести к проектам, которые могут быть трудны для понимания и относительно неясны для неопытного глаза. Использование сопрограмм позволяет вам писать код, который выглядит как минимум немного более синхронным. Думаю, теперь моя задача - выяснить, какая из этих многочисленных библиотек мне нравится, и попробовать! Рад, что спросил сейчас ...]

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


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 это удивительно (ИМХО), если вы вкладываете время. Я сделал, и это оказалось того, и я бы порекомендовал другим попробовать то же самое.


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

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


2
Хотя я согласен с тем, что статья была интересной, я думаю, что стоит рассмотреть обоснованность представленных тестов. Смотрите комментарии здесь: reddit.com/r/programming/comments/ahepg/…
— clemesha

1
@clemesha, хотя на этой странице reddit стоит отметить точку отсчета, тест был выполнен на двухъядерной машине и, вероятно, не страдал описанным фатальным недостатком. Я полагаю , что это возможно , и клиент , и сервер побежал на том же ядре, но это не кажется вероятным.
— Питер Хансен

15

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


Что не так с использованием нескольких процессов?
— Эмиль Иванов

3
Совсем ничего, отсюда и предложение использовать многопроцессорный модуль.
— Адам Хапп

11

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

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

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

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


Если вы когда-нибудь посмотрели, как реализован реактор 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 :)


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

4

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

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


4

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


2

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


2

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


1

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


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


1
Хотя это интересно и может подойти для некоторых задач, использование потоков для работы в сети плохо (особенно на Python из-за GIL). И это был как раз вопрос: четная структура или многопроцессорная обработка. Так что ваш ответ явно выходит за рамки ...
— schlamar
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.