Benim için bu aslında oldukça basit:
Altişlem seçeneği:
subprocess
olan diğer yürütülebilir çalıştırmak için etrafında temelde bir sarıcı var --- os.fork()
ve os.execve()
opsiyonel sıhhi tesisat için bazı desteği ile (ve subprocesses gelen boruları kurma. Açıkçası olabilir diğer bir işlemler arası iletişim (IPC) yuva gibi mekanizmalar, ya da Posix'e veya SysV paylaşılan bellek Ancak, aradığınız programlar tarafından desteklenen arabirimler ve IPC kanalları ile sınırlı kalacaksınız.
Genelde, herhangi bir subprocess
eşzamanlı olarak kullanılır - sadece bir dış yardımcı programı çağırır ve çıktısını geri okur veya tamamlanmasını bekler (belki sonuçlarını geçici bir dosyadan okur veya bir veritabanına gönderdikten sonra).
Bununla birlikte, yüzlerce alt işlem üretebilir ve bunları sorgulayabilir. Kendi kişisel favori yardımcı sınıfım tam olarak bunu yapıyor.
Modülün en büyük dezavantajı , subprocess
I / O desteğinin genel olarak bloke olmasıdır. Python 3.x'in gelecekteki bazı sürümlerinde bunu düzeltmek için bir taslak PEP-3145 ve alternatif bir asyncproc (Uyarı, herhangi bir dokümantasyona veya README'ye değil, doğrudan indirmeye götürür) vardır. Ayrıca fcntl
, Popen
PIPE dosya tanımlayıcılarınızı doğrudan içe aktarmanın ve değiştirmenin nispeten kolay olduğunu buldum - ancak bunun UNIX olmayan platformlar için taşınabilir olup olmadığını bilmiyorum.
(Güncelleme: 7 Ağustos 2019: ayncio alt işlemleri için Python 3 desteği: asyncio Alt İşlemleri )
subprocess
destek işleme neredeyse hiçbir olay vardır ... gerçi kullanabileceğiniz signal
modülü ve düz eski okul UNIX / Linux sinyalleri --- sanki, usulca senin süreçleri öldürerek.
Çoklu işlem seçeneği:
multiprocessing
olan mevcut (Python) kodundaki fonksiyonlarını çalıştırmak için işlemlerin bu ailenin arasında daha esnek haberleşme desteği ile. Özellikle, multiprocessing
IPC'nizi Queue
mümkün olduğunca modülün nesneleri etrafında inşa etmek en iyisidir , ancak Event
nesneleri ve çeşitli diğer özellikleri de kullanabilirsiniz (bunların bazıları, muhtemelen, mmap
desteğin yeterli olduğu platformlarda destek etrafında inşa edilmiştir ).
Python'un multiprocessing
modülü, CPython'un GIL'e (Global Yorumlayıcı Kilidi) rağmen işlemlerinizi birden çok CPU / çekirdek arasında ölçeklendirmesine izin verirken çok benzer arayüzler ve özellikler sağlamayı amaçlamaktadır threading
. İşletim sistemi çekirdeğinizin geliştiricileri tarafından yapılan tüm ince ayarlı SMP kilitleme ve tutarlılık çabasından yararlanır.
Parçacığı seçeneği:
threading
olduğu uygulamalar oldukça dar bir aralığı için I / O bağlanmış ve son derece düşük gecikme ile ilgili olan yarar ve (ortak çekirdek bellek) iplik geçiş yükü anahtarlama genel işlem (çoklu CPU çekirdeğinde ölçekte gerekmez) / bağlam değiştirme. Linux'ta bu neredeyse boş bir kümedir (Linux işlem değiştirme süreleri iş parçacığı anahtarlarına oldukça yakındır).
threading
dan uğrar Python iki büyük dezavantajları .
Elbette bunlardan biri uygulamaya özgüdür - çoğunlukla CPython'u etkiler. Bu GIL'dir. Çoğunlukla, çoğu CPython programı ikiden fazla CPU'nun (çekirdek) kullanılabilirliğinden yararlanmayacak ve performans genellikle GIL kilitleme çekişmesinden zarar görecektir .
Uygulamaya özel olmayan daha büyük sorun, evrelerin aynı belleği, sinyal işleyicileri, dosya tanımlayıcılarını ve belirli diğer işletim sistemi kaynaklarını paylaşmasıdır. Bu nedenle programcı, nesne kilitleme, istisna işleme ve kodunun diğer yönleri konusunda son derece dikkatli olmalıdır; bunlar hem incelikli hem de tüm süreci (iş parçacıkları grubu) öldürebilir, durdurabilir veya kilitleyebilir.
Karşılaştırıldığında, multiprocessing
model her işleme kendi belleğini, dosya tanımlayıcılarını, vb. Verir. Herhangi birindeki bir çökme veya işlenmemiş istisna, yalnızca o kaynağı öldürecektir ve bir çocuğun veya kardeş sürecinin ortadan kaybolmasının sağlam bir şekilde ele alınması, hata ayıklama, izole etmekten çok daha kolay olabilir. ve ileti dizilerindeki benzer sorunları düzeltmek veya çözmek.
- (Not: NumPy
threading
gibi büyük Python sistemlerinde kullanım, GIL çekişmesinden, kendi Python kodunuzun çoğundan daha az zarar görebilir. Bunun nedeni, özellikle bunu yapmak için tasarlanmış olmalarıdır; NumPy'nin yerel / ikili bölümleri, örneğin, güvenli olduğunda GIL'i serbest bırakır).
Bükülmüş seçeneği:
Twisted'ın hem zarif hem de anlaşılması çok zor olan başka bir alternatif sunduğunu da belirtmek gerekir . Temel olarak, Twisted hayranlarının dirgenler ve meşaleler ile evime saldırabileceği noktaya kadar aşırı basitleştirme riskine rağmen, Twisted herhangi bir (tek) süreçte olay odaklı işbirliğine dayalı çoklu görev sağlar.
Bunun nasıl mümkün olduğunu anlamak için (select () veya anket () veya benzer işletim sistemi sistem çağrıları select()
etrafında oluşturulabilen ) özellikleri hakkında bilgi okunmalıdır . Temel olarak, işletim sisteminin bir dosya tanımlayıcı listesindeki herhangi bir etkinliği veya bazı zaman aşımını beklerken uyku talebinde bulunma yeteneği tarafından yönlendirilir.
Bu çağrıların her birinden uyanmak select()
bir olaydır - ya bir dizi soket ya da dosya tanımlayıcıda mevcut (okunabilir) girişleri içerir ya da bazı diğer (yazılabilir) tanımlayıcılarda veya soketlerde kullanılabilir hale gelen arabelleğe alma alanı, bazı istisnai koşullar (TCP bant dışı PUSH'd paketler, örneğin) veya bir TIMEOUT.
Böylelikle Twisted programlama modeli, bu olayların işlenmesi ve ardından ortaya çıkan "ana" işleyicide döngü oluşturarak olayları işleyicilerinize göndermesine izin vererek inşa edilmiştir.
Ben şahsen , programlama modelini çağrıştıran Twisted ismini düşünüyorum ... çünkü soruna yaklaşımınız bir bakıma "çarpık" olmalı. Programınızı girdi verileri ve çıktıları veya sonuçları üzerinde bir dizi işlem olarak düşünmek yerine, programınızı bir hizmet veya arka plan programı olarak yazıyor ve çeşitli olaylara nasıl tepki vereceğini tanımlıyorsunuz. (Aslında bir Twisted programın temel "ana döngüsü" (genellikle? Her zaman?) A reactor()
) ' dır .
Twisted'ı kullanmanın en büyük zorlukları , zihninizi olaya dayalı model etrafında döndürmeyi ve ayrıca Twisted çerçevesinde işbirliği yapmak için yazılmayan herhangi bir sınıf kitaplığı veya araç setinin kullanımından kaçınmayı içerir. Bu nedenle Twisted, SSH protokolü işleme, curses için kendi modüllerini ve kendi alt işlem / Popen işlevlerini ve ilk bakışta Python standart kitaplıklarındaki şeyleri kopyalıyor gibi görünen diğer birçok modül ve protokol işleyicisini sağlar.
Hiç kullanmak istemeseniz bile Twisted'ı kavramsal düzeyde anlamanın faydalı olacağını düşünüyorum. İş parçacığı oluşturma, çoklu işleme ve hatta alt süreç işlemenin yanı sıra üstlendiğiniz herhangi bir dağıtılmış işlemde performans, çekişme ve olay işleme hakkında içgörüler sağlayabilir.
( Not: Python 3.x'in daha yeni sürümleri, async def , @ async.coroutine dekoratörü ve await anahtar sözcüğü gibi asyncio (asynchronous I / O) özellikleri ve gelecekteki destekten getiri içerir. Bunların tümü kabaca benzerdir. Bir süreç (kooperatif çoklu görev) perspektifinden bükülmüş ). (Python 3 için Twisted desteğinin mevcut durumu için şu adrese bakın: https://twistedmatrix.com/documents/current/core/howto/python3.html )
Dağıtık seçeneği:
Henüz sormadığınız, ancak dikkate almaya değer başka bir işleme alanı, dağıtılmış işlemedir. Dağıtılmış işleme ve paralel hesaplama için birçok Python aracı ve çerçevesi vardır. Kişisel olarak, kullanımı en kolay olanın o alanda en az sıklıkla kabul edilen şey olduğunu düşünüyorum.
Redis çevresinde dağıtılmış işlem oluşturmak neredeyse önemsizdir . Tüm anahtar deposu çalışma birimlerini ve sonuçları depolamak için kullanılabilir, Redis LIST'leri Queue()
benzer nesne olarak kullanılabilir ve PUB / SUB desteği benzer işlemler için kullanılabilir Event
. Çalışanlarınızı koordine etmek için tek bir örneğin kapasitesinin ötesinde ölçeklendirme için tutarlı karma ve yük devretme sağlamak üzere topolojiyi ve karma belirteç eşlemelerini depolamak için gevşek bir Redis örnekleri kümesinde çoğaltılan anahtarlarınıza hash uygulayabilir ve değerleri kullanabilirsiniz. ve aralarında veri toplama (turşu, JSON, BSON veya YAML).
Elbette, Redis çevresinde daha büyük ölçekli ve daha sofistike bir çözüm oluşturmaya başladığınızda, Celery , Apache Spark ve Hadoop , Zookeeper , vb. , Cassandra vb. Kullanılarak çözülmüş birçok özelliği yeniden uyguluyorsunuz . Bunların hepsinin hizmetlerine Python erişimi için modülleri vardır.
[Güncelleme: Python'u dağıtık sistemler arasında hesaplama açısından yoğun olarak düşünüyorsanız dikkate almanız gereken birkaç kaynak: IPython Parallel ve PySpark . Bunlar genel amaçlı dağıtılmış bilgi işlem sistemleri olsa da, özellikle erişilebilir ve popüler alt sistemler veri bilimi ve analitiğidir].
Sonuç
Python için tek iş parçacıklı, basit eşzamanlı çağrılardan alt işlemlere, yoklamalı alt işlem havuzlarına, iş parçacığı ve çoklu işlemeye, olay odaklı işbirliğine dayalı çoklu görevlere ve dağıtılmış işlemeye kadar işlem alternatifleri yelpazesine sahipsiniz.