Python'un bükülmesine karşı temiz ve hafif bir alternatif mi? [kapalı]


222

A (uzun) süre önce, eşzamanlı isteklerin aynı anda gerçekleşmesini sağlamak için birden çok iş parçacığına sahip olduğum bir web-örümcek yazdım. Bu benim Python gençliğimde, GIL ve çok iş parçacıklı kod için oluşturduğu ilişkili sıkıntıları bilmeden önceki günlerde (IE, çoğu zaman sadece seri hale geliyor!) ...

Daha sağlam hale getirmek ve daha iyi performans göstermek için bu kodu yeniden çalışmak istiyorum. Bunu yapmanın temel olarak iki yolu var: Yeni çoklu işlem modülünü 2.6+ sürümünde kullanabilirim veya bir çeşit reaktör / olaya dayalı bir model için gidebilirim. Çok daha basit ve daha az hata eğilimli olduğu için daha sonra yapmayı tercih ederim.

Dolayısıyla soru, ihtiyaçlarıma en uygun çerçeveyle ilgilidir. Aşağıda şimdiye kadar bildiğim seçeneklerin bir listesi:

  • Twisted : Python reaktör çerçevelerinin büyükbabası: ancak karmaşık ve biraz şişkin görünüyor. Küçük bir görev için dik öğrenme eğrisi.
  • Eventlet : Lindenlab'daki adamlardan . Bu tür görevlere yönelik, Greenlet tabanlı çerçeve. Yine de koda bir göz vardı ve çok güzel değil: pep8 uyumlu, baskılar ile dağınık (neden insanlar bunu bir çerçeve içinde yapıyor !?), API biraz tutarsız görünüyor.
  • PyEv : Olgunlaşmamış, şu anda onu kullanan biri gibi görünmüyor, ancak libevente dayanıyor, bu yüzden sağlam bir arka uca sahip.
  • asyncore : stdlib'den : über düşük seviyeli, sadece yerden bir şey almak için bir sürü ayak işi gibi görünüyor.
  • tornado : Bu, dinamik web sitelerini sunucuya sunmak için tasarlanmış sunucu odaklı bir ürün olmasına rağmen, zaman uyumsuz bir HTTP istemcisi ve basit bir ioloop içerir . Görünüţe göre iţi halledebiliyordu ama amacýna göre deđil. [edit: ne yazık ki Windows'ta çalışmıyor, bu benim için önemli - bu topal platformu desteklemek benim için bir gereklilik]

Kaçırdığım bir şey var mı? Şüphesiz, basitleştirilmiş bir zaman uyumsuz ağ iletişim kütüphanesinin en güzel yerine uyan bir kütüphane olmalı!

[edit: bu sayfaya gösterdiği işaret için intgr'a çok teşekkürler . En alta kaydırırsanız, bu görevi bir şekilde ele almayı amaçlayan gerçekten güzel bir proje listesi göreceksiniz. Görünüşe göre Twisted'ın başlangıcından bu yana işler gerçekten devam ediyor: insanlar artık geleneksel bir reaktör / geri çağrı odaklı olandan ziyade ko-rutin tabanlı bir çözümü destekliyor gibi görünüyor . Bu yaklaşımın faydaları daha açık ve doğrudan kodlardır: Kesinlikle geçmişte buldum, özellikle boost.asio ile çalışırkenC ++ 'da geri arama tabanlı kod, takip edilmesi zor olabilecek ve eğitimsiz göz için nispeten belirsiz olan tasarımlara yol açabilir. Ko-rutinleri kullanmak, en azından biraz daha senkronize görünen bir kod yazmanıza izin verir. Sanırım şimdi görevim, bu kütüphanelerden hangisinin görünümünü sevdiğimi bulmak ve bir şans vermek! Sevindim şimdi sordum ...]

[değiştir: belki de bu soruyu takip eden veya tökezleyen veya herhangi bir anlamda bu konuyla ilgilenen herkes için ilgi çekici: Bu iş için mevcut araçların mevcut durumunun gerçekten harika bir yazısını buldum ]


14
Python çok iş parçacıklıdır, iki iş parçacığının aynı anda Python kodunu çalıştırmasına izin vermez.
intgr

86
Sorunuzdan, cevaplarından çok daha fazla şey öğrendim.
Denis Otkidach

2
@Denis: heh, teşekkürler sanırım! Cevaplarda bazı özel göstergeler de var, özellikle intgr. Ben orada seçenekleri bir sürü biliyordum ve ben sadece cevapları bunlarla dolu istemiyordu bu yüzden ne bildiğimi yazım sorun giderdi düşündüm :)
jkp

5
> insanlar artık geleneksel reaktör / geri arama odaklı bir çözümden ziyade ko-rutin tabanlı bir çözümü tercih ediyor gibi görünüyor. Bu mantıklı bir karşılaştırma değil. "rutin bazlı çözeltiler" ve "reaktöre yönelik" çözeltiler diktir. (Python'un ortak programa sahip olmadığı gerçeğini göz ardı ederek) Sizi karmaşık platform fikirlerine maruz bırakmayacak sağlam, olgun bir ağ katmanı ile tercih edebileceğiniz programlama tarzına nasıl sahip olabileceğinizi görmek için Twisted'ın inlineCallback'lerine göz atın.
Jean-Paul Calderone

2
Eklenecek birkaç nokta: 1. Tornado Windows üzerinde çok iyi çalışıyor. selectG / Ç çoğullama için kullandığı için performans ve ölçeklenebilir değil . Ancak kasırga-pyuv ile iyi bir performans elde edebilmelisiniz . 2. Artık Python 3.3+ ve onun backport trollius'unda olay döngüsünde herhangi bir Tornado uygulamasını çalıştırmaya izin veren asyncio var (Twisted yakında desteklenecek).
schlamar

Yanıtlar:


28

Ben sevdim uyuşma hafif threading ya stackless Python microthreads veya Greenlets dayanan Python modülü. Tüm engelleme ağı G / Ç, tek bir libeventdöngü aracılığıyla şeffaf bir şekilde asenkron hale getirilir , bu yüzden gerçek bir asenkron sunucu kadar neredeyse verimli olmalıdır.

Sanırım bu şekilde Eventlet'e benziyor.

Dezavantajı, API'sinin Python'un sockets/ threadingmodüllerinden oldukça farklı olmasıdır ; uygulamanızın bir kısmını yeniden yazmanız (veya bir uyumluluk dolgu katmanı yazmanız) gerekir

Düzenleme: Görünüşe göre benzer olan bir kojen var , ancak Plethon 2.5'in gelişmiş jeneratörlerini , Greenlet'lerin yerine koroutinleri için kullanıyor. Bu, onu tutarlılık ve diğer alternatiflerden daha taşınabilir hale getirir. Ağ G / Ç doğrudan epoll / kqueue / iocp ile yapılır.


@intgr: harika bağlantılar. Her ikisini de bir zamanlar görmüştüm, bunlar kızardı görmeyi umduğum şeyler. +1
jkp

3
Görünüşe göre eşzamanlılık, dört yıl önceki son güncelleme ile ölü bir proje.
Gewthen

proje öldü, Hyves de öyle!
Bahadir Cambel

1
Python 2.5'ten bu yana çok şey oldu. Python 3.5 asyncio harika.
Joseph Sheedy

99

Twisted karmaşık, bu konuda haklısın. Twisted edilir değil kabartılan.

Buraya bir göz atarsanız : http://twistedmatrix.com/trac/browser/trunk/twisted internetin birçok protokolünden oluşan organize, kapsamlı ve çok iyi test edilmiş bir paketin yanı sıra yazmak için yardımcı kod bulacaksınız ve çok sofistike ağ uygulamaları kurmanız gerekir. Şişkinliği kapsamlı bir şekilde karıştırmam.

Twisted belgelerinin ilk bakışta en kullanıcı dostu olmadığı iyi biliniyor ve bunun talihsiz sayıda insanı geri çevirdiğine inanıyorum. Ama Twisted inanılmaz (IMHO) zaman koyarsanız. Yaptım ve buna değer olduğunu kanıtladı ve aynı denemek için başkalarına tavsiye ederim.


4
@clemesha: belki haklısınız ve yüklü değil, ama basit bir şey yapmak için kafamı dolaşmak için biraz fazla gibi görünüyor. Async programlamayı anlıyorum, C ++ 'da boost :: asio ile çalıştım, bu yüzden kavramlar yeni değil, ama bükülmüş şeyler yapmakla uyumlu olan tüm gumph: django web şeyler için olduğu gibi tamamen yeni bir dünya. Yine web şeyler yaparken hafif WSGI kodu ile çalışmak ve sadece ihtiyacım olanı birlikte takın. Kurslar için atlar sanırım.
JKP

7
@clemesha: erm, bugün bir göz atmak için dalmayı aldım: 20MB'da bükülmüş ağırlıklar! Çekirdek bile 12MB .... bu şişirilmemiş değilse, tam olarak ne olduğundan emin değilim.
jkp

29
Temel Twisted API'leri oldukça küçüktür (reaktör, ertelenmiş, protokol). Twisted kodunun çoğu bu temelleri kullanan asenkron protokol uygulamalarıdır. "Şişkinlik" burada (ya da çoğu durumda) yararlı bir sıfat değildir. Twisted'ın boyutu yaptığı miktar için makul.
daf

56

gevent edilir eventlet temizledik .

API açısından, standart kütüphaneyle (özellikle, iş parçacığı ve çok işlemli modüller) aynı kuralları izler. Yani Kuyruk ve Etkinlik gibi tanıdık şeyleriniz var .

Reaktör uygulaması olarak yalnızca libevent'i ( güncelleme: libev 1.0'dan beri ) destekler, ancak libevent-http tabanlı hızlı bir WSGI sunucusuna sahiptir ve diğer sorguların çoğunda olduğu gibi bir iş parçacığı havuzu kullanmak yerine libevent-dns aracılığıyla DNS sorgularını çözer yapmak. ( güncelleme: 1.0 c-ares zaman uyumsuz DNS sorguları yapmak için kullanıldığından, threadpool da bir seçenektir.)

Eventlet gibi, greenlets kullanarak geri aramaları ve Ertelemeleri gereksiz hale getirir .

Örneklere göz atın: Birden çok URL'nin aynı anda indirilmesi , uzun oylama web sohbeti .


4
İkinci kez bakacağım - Çözümlerin çoğunu inceledikten sonra, gevent benim için çok iyi çalıştı. Mevcut programımın daha iyi kısmını korumama izin verdi ve gerekli değişiklikler önemsizdi - En iyisi, kodun 3, 4, 5, ... yıl içinde korunması gerekiyorsa, yine de gevent'e aşina olmayan herkese mantıklı, Twisted için en büyük showtopper güçlü öğrenme eğrisidir, bu sadece uygularken değil, aynı zamanda bakım sırasında çizgide daha da aşağıya neden olur ...
Martin Tournoij

27

Bu çerçevelerin gerçekten ilginç bir karşılaştırması , blogunda Nicholas Piël tarafından derlendi: okumaya değer!


2
Makalenin ilginç bir okuma olduğunu kabul etsem de, sunulan kıyaslama ölçütlerinin geçerliliğini dikkate almaya değer. Buradaki yorumlara bakın: reddit.com/r/programming/comments/ahepg/…
clemesha

1
@clemesha, bu reddit sayfasındaki nokta kayda değer olsa da, kıyaslama çift çekirdekli bir makinede yapıldı ve muhtemelen açıklanan ölümcül kusurdan muzdarip değildi. Bunun varsayalım mümkün istemci ve sunucu koştu ikisi de aynı çekirdek üzerinde, ancak olası görünmüyor.
Peter Hansen

15

Bu çözümlerin hiçbiri, GIL'in CPU paralelliğini önlediği gerçeğinden kaçınmaz - bunlar zaten iş parçacıklarıyla olan IO paralelliğini elde etmenin daha iyi yoludur. Daha iyi IO yapabileceğinizi düşünüyorsanız, elbette bunlardan birini takip edin, ancak darboğazınız sonuçları işliyorsa, burada çok işlem modülü hariç hiçbir şey yardımcı olmaz.


Birden çok işlem kullanmanın nesi yanlış?
Emil Ivanov

3
Hiçbir şey, bu nedenle çok işlem modülünü kullanma önerisi.
Adam Hupp

11

Ben Twisted şişirilmiş aramak için kadar gitmek olmaz, ama başınızı etrafında sarmak zor. 'Küçük görevler' için her zaman biraz daha kolay bir şey istediğim için uzunca bir süre öğrenmeye yerleşmekten kaçındım.

Ancak, şimdi onunla biraz daha çalıştı tüm piller dahil olması çok güzel olduğunu söylemek gerekir.

Çalıştığım diğer tüm asenkron kütüphaneler, göründüklerinden çok daha az olgunlaşıyor. Twisted'ın olay döngüsü sağlam.

Dik Twisted öğrenme eğrisinin nasıl çözüleceğinden emin değilim. Birisi çatallanırsa ve geriye dönük uyumluluk sarsıntılarını ve ölü projeleri kaldırmak gibi birkaç şeyi temizlerse yardımcı olabilir. Ama sanırım olgun yazılımın doğası bu.


Gtk reaktörünün Windows altında nasıl uygulandığını (her 10 ms'de bir sert yoklama: twistedmatrix.com/trac/browser/trunk/twisted/internet/… ) hiç aradıysanız , buna "olgun"
diyemezsiniz

2
Merhaba @ schlamar. Bu kötü kesmek, GTK + 'daki bazı ciddi hatalar için, güç verimliliği hakkında çok daha az endişenin olduğu günlerde bir çözüm olarak uygulandı :). Ancak, Twisted'ın güzelliği, bu hatayı bir kez alabilir , çerçevede düzeltebiliriz ve kullanıcılarımızın bu konuda endişelenmesine gerek yoktur. Bu sorunu ele alan ve ondan kurtulan bir düzeltmeye katkıda bulunmak ister misiniz (kullanımdan kaldırılır ve daha sonra kaldırılır) PortableGtkReactor?
Glif

1
@Glyph Bu sorunların bir kısmı hala ele alındığı için başka biri bu sorunu çözmek istiyorsa twistedmatrix.com/trac/ticket/4744#comment:2 üzerine faydalı tavsiyeler ekledim . BTW, iki olay döngüsü arasında geri aramaları zamanlayarak bunu çok daha verimli bir şekilde çözebilirdiniz.
schlamar

7

Kamaelia henüz bahsedilmedi. Eşzamanlılık modeli, gelen kutuları ve giden kutuları arasında iletiyi ileterek bileşenleri birbirine bağlamaya dayanır. İşte kısa bir genel bakış.


5
Bir uygulama için kamaelia kullandım - son derece acı vericiydi. IMHO Python'da eşzamanlılık için başka, daha iyi seçenekler var (çoğu yukarıda belirtilmiştir)
Ben Ford

7

Bazı şeyler için bükülmüş kullanmaya başladım. Güzelliği neredeyse "şişirilmiş" çünkü. Orada hemen hemen tüm ana protokoller için konektörler var. Komutları alıp bir irc sunucusuna gönderecek, birisine e-posta gönderecek, bir komut çalıştıracak, bir NNTP sunucusundan okuyacak ve bir web sayfasını değişiklikler için izleyecek bir jabber botuna sahip olabilirsiniz. Kötü haber, tüm bunları yapabileceği ve OP'nin açıkladığı gibi basit görevler için işleri aşırı derecede karmaşık hale getirebileceğidir. Python'un avantajı, sadece ihtiyacınız olanı dahil etmenizdir. Bu yüzden indirme 20mb olsa da, sadece 2mb kütüphaneyi (hala çok olan) ekleyebilirsiniz. Bükülmüş ile en büyük şikayetim, örnekleri içermesine rağmen, kendi başınıza olduğunuz temel bir tcp sunucusunun ötesinde bir şey.

Bir python çözümü olmasa da, node.js'nin geç saatlerde çok daha fazla çekiş elde ettiğini gördüm. Aslında daha küçük projeler için bakmayı düşündüm ama sadece javascript duyduğumda saçmalıyım :)


Ben büyük bir Python hayranıyım. - Douglas Crockford'dan “Javascript - The good parts” a bakın (3, 4 video). Ve CoffeeScript'e göz atın. JS'nin Sözdizimi hariç Python'un sahip olması gereken şeyleri olduğu ortaya çıktı haha. CS bunu hafifletmeye çalıştı, ama biraz sakar ...
Robert Siemer

4

Konuyla ilgili iyi bir kitap var: Abe Twett'in "Twisted Network Programming Essentials". Örnekler çok Pythonic kodunun nasıl yazılacağını ve kişisel olarak bana şişirilmiş bir çerçeveye dayanarak bana vurmadığını gösteriyor. Kitaptaki çözümlere bakın, eğer temiz değillerse, temizliğin ne anlama geldiğini bilmiyorum.

Tek gizemim Ruby gibi diğer çerçevelerle aynı. Endişeleniyorum, ölçek büyütüyor mu? Bir müşteriyi ölçeklenebilirlik sorunları yaşayacak bir çerçeveye adamaktan nefret ederim.


4

Whizzer , pyev kullanan küçük bir asenkron soket çerçevesidir. Çok hızlı, öncelikle pyev yüzünden. Bazı küçük değişikliklerle bükülmüş olarak benzer bir arayüz sağlamaya çalışır.


2

Ayrıca Syncless'i deneyin . Coroutine tabanlıdır (yani Concurrence, Eventlet ve gevent'e benzer). Socket.socket, socket.gethostbyname (vb.), Ssl.SSLSocket, time.sleep ve select.select için engellenmeyen engellemesiz değiştirmeler uygular. Hızlı. Stackless Python ve libevent'e ihtiyacı var. C (Pyrex / Cython) ile yazılmış zorunlu bir Python uzantısı içerir.


2

S Senkronizasyonun iyiliğini onaylayın . Libev (libevent'in daha yeni, daha temiz ve daha iyi performans versiyonu) kullanabilir. Bazı zamanlar, libevent kadar destek vermez, ancak şimdi geliştirme süreci daha da ileri gider ve çok yararlıdır.



0

Oldukça farklı bir yaklaşım gerektiren PyWorks'e göz atabilirsiniz. Nesne örneklerinin kendi evrelerinde çalışmasına izin verir ve işlev çağrısını o nesneye zaman uyumsuz hale getirir.

Bir sınıfın nesne yerine Görev'den miras almasına izin verin ve bu zaman uyumsuz, tüm yöntem çağrıları Proxy'lerdir. Dönüş değerleri (ihtiyacınız varsa) Gelecek vekillerdir.

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 adresinde bulunabilir.


1
Bu ilginç olsa da ve bazı görevler için uygun olsa da, ağ oluşturma için iş parçacığı kullanmak kötü performans gösterir (özellikle GIL nedeniyle Python'da). Ve bu tam olarak soru idi: olaylı bir çerçeve ya da çok işlemli. Bu yüzden cevabınız açıkça kapsam dışı ...
schlamar
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.