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


222

Нещодавно я писав веб-павук, який багатопотоково читав, щоб одночасно виникати одночасні запити. Це було в моїй Python-молодості, за дні, перш ніж я знав про GIL і пов'язані з цим неприємності для багатопотокового коду (IE, більшість часу речі просто закінчуються серіалізованими!) ...

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

Тож питання стосується того, яка рамка найкраще відповідає моїм потребам. Далі наведено список варіантів, про які я знаю дотепер:

  • Скручений : дідусь із реакторних каркасів Python: здається складним і трохи роздутим. Крута крива навчання для невеликого завдання.
  • Eventlet : Від хлопців з lindenlab . Рамка на базі Greenlet, орієнтована на подібні завдання. Я хоч подивився на код, і він не надто гарний: несумісний з pep8, розсипаний відбитками (чому люди роблять це в рамках !?), API здається трохи непослідовним.
  • PyEv : Незрілий , здається, ніхто зараз не використовує його, хоча він заснований на libevent, тому він має надійний підхід.
  • asyncore : З stdlib: über низького рівня, схоже, що багато ніжних робіт, пов'язаних просто для того, щоб щось зірвати з землі.
  • tornado : Хоча це серверно-орієнтований продукт, призначений для серверних динамічних веб-сайтів, він оснащений клієнтом async HTTP та простим ioloop . Схоже, це може виконати роботу, але не те, що було призначено. [редагувати: на жаль, не працює в Windows, що для мене це рахує - це для мене вимога підтримувати цю кульгаву платформу]

Чи є щось, що я взагалі пропустив? Звичайно, там повинна бути бібліотека, яка відповідає місцем спрощеної асинхронної мережевої бібліотеки!

[редагувати: велике спасибі intgr за його вказівник на цю сторінку . Якщо прокрутити донизу, ви побачите, що існує справді приємний перелік проектів, які мають на меті вирішити це завдання так чи інакше. Насправді здається, що справи справді просунулися з моменту створення Twisted: зараз, здається, люди віддають перевагу спільному рутинному рішенню, а не традиційному, орієнтованому на реактор / зворотний виклик. Переваги такого підходу ясніше, пряміший код: я, звичайно, виявив минуле, особливо при роботі з boost.asioв C ++ цей код на основі зворотного виклику може призвести до складних конструкцій та відносно незрозумілих для нетренованого ока. Використання спільних процедур дозволяє писати код, який виглядає принаймні трохи синхронніше. Я думаю, зараз моє завдання - розібратися, яка з цих багатьох бібліотек мені подобається зовнішній вигляд, і дати їй піти! Радий, що я запитав зараз ...]

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


14
Python є багатопотокової, вона просто не дозволяє двом потокам запустити код Python одночасно.
intgr

86
Я дізнався набагато більше з вашого запитання, ніж з відповідей на нього.
Денис Откідач

2
@Denis: хе, дякую, мабуть! У відповідях також було кілька хороших покажчиків, зокрема, intgr. Я знав про багато варіантів там, і я не просто хотів, щоб відповіді були запаковані з тими, тому я подумав, що пітиму на проблему з прописанням того, що знаю :)
jkp

5
> Зараз люди, здається, віддають перевагу спільному рутинному рішенню, а не традиційному, орієнтованому на реактор / зворотний виклик. Це не є розумним порівнянням. "рішення, що базуються на рутині" і "орієнтовані на реактор", є ортогональними. (Ігноруючи той факт, що в Python немає підпрограм) Погляньте на inlineCallbacks Twisted, щоб побачити, як ви можете мати стиль програмування, який, здається, ви віддаєте перевагу, з міцним, зрілим мережевим шаром, який не збирається піддавати вас складним ідіосинкрасіям платформи.
Жан-Поль Кальдероне

2
Ще кілька моментів, які слід додати: 1. Торнадо працює дуже добре в Windows. Це просто не настільки ефективно і масштабується, оскільки він використовується selectдля мультиплексування вводу / виводу. Але ви повинні мати можливість отримати гідне виконання цього ефекту за допомогою торнадо-піву . 2. Зараз в Python 3.3+ є асинціо і його backport trollius, який дозволяє запускати будь-яку програму Tornado у своєму циклі подій (Twisted буде підтримано незабаром).
шламар

Відповіді:


28

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

Я гадаю, що подібний до Eventlet таким чином.

Мінус у тому, що його API сильно відрізняється від модулів sockets/ threadingмодулів Python ; вам потрібно переписати неабияку частину своєї програми (або написати прошивний шар сумісності)

Редагувати: Здається, є також коген , який схожий, але він використовує розширені генератори Python 2.5 для своїх процедур замість Greenlets. Це робить його більш портативним, ніж узгодження та інші альтернативи. Мережевий введення / виведення здійснюється безпосередньо за допомогою epoll / kqueue / iocp.


@intgr: чудові посилання. Я бачив обох цих раніше, колись це були речі, які я сподівався побачити розмитими. +1
jkp

3
Схоже, що узгодження - це мертвий проект, останній оновлення якого було чотири роки тому.
Gewthen

проект мертвий, так само і Hyves!
Bahadir Cambel

1
З Python 2.5 відбулося багато. asyncio в Python 3.5 - це чудово.
Джозеф Шеді

99

Скручений складний, ви маєте рацію з цим. Скручений не роздутий.

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

Добре відомо, що документація Twisted не є найзручнішою з першого погляду, і я вважаю, що це відвертає нещасну кількість людей. Але Twisted є дивовижним (IMHO), якщо поставити час. Я це зробив, і це виявилося вартим, і я рекомендував би іншим спробувати те саме.


4
@clemesha: можливо, ти маєш рацію, і це не навантажується, але все ж здається, що є трохи занадто багато, щоб змусити мою голову зробити щось просте. Я розумію програмування асинхронізації, я працював у C ++ з boost :: asio, тому поняття не нові, але все це гумфа, яка конкурує з вивертанням: це цілий новий світ, як і джанго для веб-речей. Знову, коли я роблю веб-речі, я працюю з полегшеним кодом WSGI і підключаю лише те, що мені потрібно. Я думаю, коні на курси.
jkp

7
@clemesha: Ем, я сьогодні зайнявся, щоб подивитись: кручена важить в 20 МБ! Навіть ядро ​​12МБ .... якщо це не роздуто, я не впевнений, що це таке.
jkp

29
Основні API Twisted досить малі (реактор, відкладений, протокол). Більшість кодів Twisted - це реалізація протоколу асинхронізації, використовуючи ці основи. Тут не є корисним прикметником (або справді в більшості випадків). Закручений розмір є розумним для кількості матеріалів, які він робить.
daf

56

GEvent є eventlet очищення .

Для API це дотримується тих самих умов, що і стандартна бібліотека (зокрема, модулі для обробки різьби та багатопроцесорної обробки), де це має сенс. Отже, у вас є знайомі речі, такі як черга та подія потрібно працювати.

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

Як і eventlet, він робить непотрібними зворотні дзвінки та відстрочки, використовуючи greenlets .

Ознайомтеся з прикладами: одночасне завантаження декількох URL-адрес , довге веб-чат опитування .


4
Я другий гевент - Переглянувши багато рішень, gevent працював для мене дуже добре. Це дозволило мені зберегти більшу частину моєї існуючої програми, а необхідні зміни були тривіальними - Найкраще, якщо код потрібно підтримувати через 3, 4, 5, ... роки, він все одно робить сенс для тих, хто не знайомий з gevent, найбільшим шоустопом для Twisted є сильна крива навчання, це спричиняє проблеми не тільки при впровадженні, а й далі вниз по лінії під час технічного обслуговування ...
Martin Tournoij,

27

По-справжньому цікаве порівняння таких рамок склав Ніколас Піль у своєму блозі: це варто прочитати!


2
Хоча я погоджуюся, що стаття була цікавою для читання, я вважаю, що варто врахувати обгрунтованість представлених орієнтирів. Дивіться коментарі тут: reddit.com/r/programming/comments/ahepg/…
clemesha

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

15

Жодне з цих рішень не уникне того факту, що GIL запобігає паралелізму процесора - вони просто кращі способи отримати паралелізм IO, який у вас вже є з потоками. Якщо ви думаєте, що ви можете зробити кращий IO, будь-якими способами переслідуйте один із них, але якщо ваше вузьке місце знаходиться в обробці результатів, тут нічого не допоможе, крім багатопроцесорного модуля.


Що не так у використанні декількох процесів?
Еміль Іванов

3
Нічого, отже, пропозиція використовувати багатопроцесорний модуль.
Адам Хупп

11

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

Однак тепер, коли я працював з цим ще деяким, я повинен сказати, що всі батареї включені - ДУЖЕ приємно.

Усі інші бібліотеки асинхронізації, з якими я працював, закінчилися набагато менш зрілими, ніж вони навіть здаються. Петля подій 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, якщо хтось інший хоче вирішити цю проблему, тому що деякі проблеми тез все ще існують. До речі, ви могли б вирішити це набагато ефективніше, запланувавши зворотний зв'язок між двома петлями подій.
шламар

7

Камалія поки не згадується. Його модель одночасності базується на з'єднанні компонентів з повідомленнями, що проходять між вхідними та вихідними. Ось короткий огляд.


5
Я використовував камаелію для програми - це було надзвичайно боляче. ІМХО є й інші, кращі варіанти спільної дії в пітоні (більшість з яких згадується вище)
Бен Форд

7

Я почав використовувати скручені для деяких речей. Краса його майже в тому, що вона "роздута". Є з'єднувачі майже для будь-якого з основних протоколів. Ви можете мати бот-jabber, який буде приймати команди та публікувати на irc-сервері, надсилати їх електронною поштою комусь, виконувати команду, читати з сервера NNTP та стежити за веб-сторінкою щодо змін. Погана новина полягає в тому, що вона може зробити все це і може зробити речі надто складними для простих завдань, як це пояснила ОП. Перевагою python є те, що ви включаєте лише те, що вам потрібно. Тож завантаження може становити 20 Мб, але ви можете включати лише 2 МБ бібліотек (що ще багато). Моя найбільша скарга зі скрученими, хоча вони включають приклади, що завгодно, ніж базовий сервер tcp, який ви маєте самостійно.

Хоча це не рішення python, я бачив, що node.js значно пізніше отримує тягу. Насправді я розглядав питання щодо більш дрібних проектів, але я просто притискаюся, коли чую JavaScript :)


Я великий шанувальник Python. - Перевірте «Javascript - хороші частини» від Дугласа Крокфорда (3, 4 відео). І зазирнути в CoffeeScript. Виявляється, у JS є речі, які повинен мати Python, крім синтаксису, ха-ха. CS намагався пом'якшити це, але трохи незграбний у цьому ...
Роберт Сімер

4

Є гарна книга з цього приводу: "Основи програмованого мережевого програмування", автор Abe Fettig. На прикладах показано, як писати дуже пітонічний код, і особисто мені не вражайте мене, як на основі роздутого фрейму. Подивіться на рішення в книзі, якщо вони не чисті, то я не знаю, що означає чистота.

Моя єдина загадка - це те саме, що я маю з іншими рамками, на кшталт Рубі. Я хвилююся, чи збільшується вона? Мені б не хотілося залучати клієнта до структури, яка матиме проблеми зі масштабуванням.


4

Whizzer - це крихітний асинхронний каркас сокета, який використовує pyev. Це дуже швидко, в першу чергу через пієв. Він намагається надати подібний інтерфейс у вигляді суттєвих змін.


2

Спробуйте також Syncless . Він заснований на кореневій програмі (тому він схожий на Concurrence, Eventlet та gevent). Він реалізує незамінні блокуючі заміни для socket.socket, socket.gethostbyname (тощо), ssl.SSLSocket, time.sleep та select.select. Це швидко. Він потребує безстатевого пітона та звільненого. Він містить обов'язкове розширення Python, написане на C (Pyrex / Cython).


2

Я підтверджую доброту безсинхронності . Він може використовувати libev (більш нову, чистішу та кращу ефективність версії libevent). Деякий раз тому він не має такої підтримки, як libevent, але зараз процес розробки проходить далі і дуже корисний.



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.