मैं पायथन में थ्रेडिंग का उपयोग कैसे कर सकता हूं?


1277

मैं पायथन में थ्रेडिंग को समझने की कोशिश कर रहा हूं। मैंने प्रलेखन और उदाहरणों को देखा है, लेकिन काफी स्पष्ट रूप से, कई उदाहरण अत्यधिक परिष्कृत हैं और मुझे उन्हें समझने में परेशानी हो रही है।

मल्टी-थ्रेडिंग के लिए विभाजित किए गए कार्यों को आप स्पष्ट रूप से कैसे दिखाते हैं?


31
इस विषय के आसपास एक अच्छी सामान्य चर्चा जेफ नुप्प द्वारा पायथन की हार्डेस्ट समस्या में पाई जा सकती है । संक्षेप में, ऐसा लगता है कि सूत्रण शुरुआती लोगों के लिए नहीं है।
मैथ्यू वॉकर

111
हाहा, मुझे लगता है कि थ्रेडिंग हर किसी के लिए है, लेकिन शुरुआती थ्रेडिंग के लिए नहीं हैं :)))))
Bohdan

42
बस यह बताने के लिए कि लोगों को सभी उत्तरों को पढ़ना चाहिए क्योंकि बाद में यकीनन बेहतर होते हैं क्योंकि नई भाषा सुविधाओं का फायदा उठाया जाता है ...
ग्विन इवांस

5
याद रखें कि C में अपना मुख्य तर्क लिखें और ctypes के माध्यम से कॉल करके वास्तव में पायथन थ्रेडिंग का लाभ उठाएं।
आका १२२०४ जू

4
मैं बस जोड़ना चाहता था कि PyPubSub थ्रेड प्रवाह को नियंत्रित करने के लिए संदेश भेजने और प्राप्त करने का एक शानदार तरीका है
ytpillai

जवाबों:


1416

चूंकि यह सवाल 2010 में पूछा गया था, पायथन के साथ मैप और पूल के साथ सरल मल्टीथ्रेडिंग करने का वास्तविक सरलीकरण किया गया है ।

नीचे दिया गया कोड एक लेख / ब्लॉग पोस्ट से आता है जिसे आपको निश्चित रूप से जांचना चाहिए (कोई संबद्धता नहीं) - एक पंक्ति में समानांतरवाद: दिन के लिए एक बेहतर मॉडल थ्रेडिंग कार्य । मैं नीचे संक्षेप में बताऊंगा - यह कोड की कुछ पंक्तियाँ होने के कारण समाप्त होती है:

from multiprocessing.dummy import Pool as ThreadPool
pool = ThreadPool(4)
results = pool.map(my_function, my_array)

इसका बहु-संस्करण संस्करण कौन सा है:

results = []
for item in my_array:
    results.append(my_function(item))

विवरण

मानचित्र एक शांत सा कार्य है, और आपके पायथन कोड में समानता को आसानी से इंजेक्ट करने की कुंजी है। उन अपरिचित लोगों के लिए, नक्शा लिस्प जैसी कार्यात्मक भाषाओं से उठाया गया है। यह एक ऐसा फंक्शन है जो किसी अन्य फंक्शन को एक सीक्वेंस पर मैप करता है।

मानचित्र हमारे लिए अनुक्रम पर पुनरावृत्ति को संभालता है, फ़ंक्शन को लागू करता है, और अंत में एक आसान सूची में सभी परिणामों को संग्रहीत करता है।

यहां छवि विवरण दर्ज करें


कार्यान्वयन

मैप फ़ंक्शन के समानांतर संस्करण दो पुस्तकालयों द्वारा प्रदान किए जाते हैं: मल्टीप्रोसेसिंग, और इसके अल्प ज्ञात, लेकिन समान रूप से शानदार स्टेप चाइल्ड: मल्टीप्रोसेसिंग।मम्मी।

multiprocessing.dummyबिल्कुल मल्टीप्रोसेसिंग मॉड्यूल के समान है, लेकिन इसके बजाय थ्रेड्स का उपयोग करता है ( एक महत्वपूर्ण अंतर - गहन-गहन कार्यों के लिए कई प्रक्रियाओं का उपयोग करता है; थ्रेड्स के लिए (और दौरान) I / O ):

मल्टीप्रोसेसिंग। मम्मी मल्टीप्रोसेसिंग के एपीआई की नकल करती है, लेकिन थ्रेडिंग मॉड्यूल के चारों ओर एक आवरण से अधिक नहीं है।

import urllib2
from multiprocessing.dummy import Pool as ThreadPool

urls = [
  'http://www.python.org',
  'http://www.python.org/about/',
  'http://www.onlamp.com/pub/a/python/2003/04/17/metaclasses.html',
  'http://www.python.org/doc/',
  'http://www.python.org/download/',
  'http://www.python.org/getit/',
  'http://www.python.org/community/',
  'https://wiki.python.org/moin/',
]

# Make the Pool of workers
pool = ThreadPool(4)

# Open the URLs in their own threads
# and return the results
results = pool.map(urllib2.urlopen, urls)

# Close the pool and wait for the work to finish
pool.close()
pool.join()

और समय के परिणाम:

Single thread:   14.4 seconds
       4 Pool:   3.1 seconds
       8 Pool:   1.4 seconds
      13 Pool:   1.3 seconds

कई तर्क पारित करना ( केवल पायथन 3.3 और बाद में इस तरह काम करता है ):

कई सरणियों को पास करने के लिए:

results = pool.starmap(function, zip(list_a, list_b))

या एक स्थिरांक और एक सरणी पास करने के लिए:

results = pool.starmap(function, zip(itertools.repeat(constant), list_a))

यदि आप पायथन के पुराने संस्करण का उपयोग कर रहे हैं, तो आप इस समाधान के माध्यम से कई तर्क पारित कर सकते हैं )।

( उपयोगी टिप्पणी के लिए user136036 का धन्यवाद ।)


90
यह केवल वोटों की कमी है क्योंकि यह बहुत नए सिरे से पोस्ट किया गया है। यह उत्तर खूबसूरती से काम करता है और 'मानचित्र' कार्यक्षमता को प्रदर्शित करता है जो यहां के अन्य उत्तरों की तुलना में वाक्य रचना को समझने में बहुत आसान है।
निष्क्रिय

25
क्या यह भी थ्रेड है और प्रक्रिया नहीं है? ऐसा लगता है कि यह मल्टीप्रोसेस करने का प्रयास करता है! = मल्टीथ्रेड
AturSams

72
वैसे, दोस्तों, आप with Pool(8) as p: p.map( *whatever* )बुककीपिंग लाइनों से भी लिख सकते हैं और छुटकारा पा सकते हैं।

11
@BarafuAlbino: जैसा कि उपयोगी है, यह शायद ध्यान देने योग्य है कि यह केवल पायथन 3.3+ में काम करता है
fuglede

9
आप इस उत्तर को कैसे छोड़ सकते हैं और यह उल्लेख नहीं कर सकते हैं कि यह केवल I / O संचालन के लिए उपयोगी है? यह केवल एक ही धागे पर चलता है जो अधिकांश मामलों के लिए बेकार है, और वास्तव में इसे सामान्य तरीके से करने की तुलना में धीमा है
फ्रोबोट

714

यहां एक सरल उदाहरण दिया गया है: आपको कुछ वैकल्पिक URL आज़माने और पहले वाले की सामग्री का जवाब देने की आवश्यकता है।

import Queue
import threading
import urllib2

# Called by each thread
def get_url(q, url):
    q.put(urllib2.urlopen(url).read())

theurls = ["http://google.com", "http://yahoo.com"]

q = Queue.Queue()

for u in theurls:
    t = threading.Thread(target=get_url, args = (q,u))
    t.daemon = True
    t.start()

s = q.get()
print s

यह एक ऐसा मामला है जहां थ्रेडिंग का उपयोग एक साधारण अनुकूलन के रूप में किया जाता है: प्रत्येक उप-प्रलेख अपनी सामग्री को कतार में रखने के लिए, हल करने और प्रतिक्रिया देने के लिए URL की प्रतीक्षा कर रहा है; प्रत्येक धागा एक डेमॉन है (यदि मुख्य धागा समाप्त होता है तो यह प्रक्रिया नहीं रखेगा - जो कि सामान्य से अधिक है); मुख्य धागा सभी उप-थ्रेड्स को शुरू करता है get, कतार पर प्रतीक्षा करता है जब तक कि उनमें से एक ने नहीं किया है put, तब परिणाम निकालता है और समाप्त हो जाता है (जो किसी भी सबथ्रेड्स को ले जाता है जो अभी भी चल रहे हैं, क्योंकि वे डेमन थ्रेड हैं)।

पायथन में थ्रेड्स का उचित उपयोग हमेशा I / O संचालन से जुड़ा होता है (चूंकि CPython CPU-बाउंड कार्यों को चलाने के लिए कई कोर का उपयोग नहीं करता है, थ्रेडिंग का एकमात्र कारण प्रक्रिया को रोकना नहीं है, जबकि कुछ I / O के लिए प्रतीक्षा है। )। कतारें लगभग अपरिहार्य रूप से थ्रेड्स और / या कार्य के परिणामों को एकत्रित करने का सबसे अच्छा तरीका है, वैसे, और वे आंतरिक रूप से थ्रेडसेफ़ हैं, इसलिए वे आपको ताले, स्थितियों, घटनाओं, सेमेस्टर और अन्य इंटर के बारे में चिंता करने से बचाते हैं। -सहयोग समन्वय / संचार अवधारणाओं।


10
धन्यवाद फिर से, MartelliBot। मैं उदाहरण नवीनीकृत किया है प्रतिक्रिया करने के लिए यूआरएल के लिए सभी के लिए इंतजार करना: आयात कतार, थ्रेडिंग, urllib2 q = Queue.Queue () यूआरएल = '' ' a.com B.com । C.com' '' विभाजन () urls_received = 0 def get_url (q, url): req = urllib2.Request (url) resp = urllib2.urlopen (req) q.put (resp.read ()) वैश्विक urls -received urls_received + = 1 प्रिंट urls_received u in urls: u। = थ्रेडिंग। थ्रेड (लक्ष्य = get_url, args = (q, u)) t.daemon = True t.start () जबकि q.empty () और urls_received <len (urls) s = q.get () प्रिंट s
htmldrum

3
@ जेआरएम: यदि आप नीचे दिए गए अगले उत्तर को देखते हैं, तो मुझे लगता है कि थ्रेड समाप्त होने तक इंतजार करने का एक बेहतर तरीका join()विधि का उपयोग करना होगा, क्योंकि वे मुख्य थ्रेड का इंतजार तब तक करेंगे जब तक वे लगातार प्रोसेसर द्वारा उपभोग किए बिना नहीं होते। मान की जाँच करना। @ एलेक्स: धन्यवाद, यह वही है जो मुझे समझने की जरूरत है कि थ्रेड्स का उपयोग कैसे करें।
krs013

6
Python3 के लिए, 'import urllib2' को 'import urllib.request as urllib2' से बदलें। और प्रिंट स्टेटमेंट में कोष्ठक डालें।
हार्वे

5
अजगर 3 के लिए Queueमॉड्यूल नाम बदलें queue। विधि का नाम समान है।
JSmyth

2
मैं ध्यान देता हूं कि समाधान केवल एक पृष्ठ का प्रिंट आउट लेगा। कतार से दोनों पृष्ठों को प्रिंट करने के लिए बस फिर से कमांड चलाएँ: s = q.get() print s @ krs013 आपको कतार की आवश्यकता नहीं है joinक्योंकि () अवरुद्ध है।
टॉम एंडरसन

256

नोट : अजगर में वास्तविक बनता है के लिए, आप का उपयोग करना चाहिए बहु मॉड्यूल कई प्रक्रियाओं है कि (वैश्विक दुभाषिया ताला की वजह से समानांतर में निष्पादित, अजगर धागे interleaving प्रदान कांटा करने के लिए क्रमानुसार, समानांतर में नहीं है, लेकिन वे वास्तव में निष्पादित, और केवल हैं उपयोगी जब मैं / हे संचालन interleaving)।

हालांकि, यदि आप केवल इंटरलेविंग (या I / O संचालन कर रहे हैं जो वैश्विक दुभाषिया लॉक के बावजूद समानांतर किया जा सकता है) की तलाश कर रहे हैं, तो थ्रेडिंग मॉड्यूल शुरू करने की जगह है। वास्तव में एक सरल उदाहरण के रूप में, आइए समानांतर में संक्षेप उप योगों द्वारा एक बड़ी रेंज को समेटने की समस्या पर विचार करें:

import threading

class SummingThread(threading.Thread):
     def __init__(self,low,high):
         super(SummingThread, self).__init__()
         self.low=low
         self.high=high
         self.total=0

     def run(self):
         for i in range(self.low,self.high):
             self.total+=i


thread1 = SummingThread(0,500000)
thread2 = SummingThread(500000,1000000)
thread1.start() # This actually causes the thread to run
thread2.start()
thread1.join()  # This waits until the thread has completed
thread2.join()
# At this point, both threads have completed
result = thread1.total + thread2.total
print result

ध्यान दें कि उपरोक्त एक बहुत ही मूर्खतापूर्ण उदाहरण है, क्योंकि यह पूरी तरह से I / O नहीं करता है और वैश्विक दुभाषिया लॉक के कारण CPython में क्रमिक रूप से अलबेत इंटरलीव्ड (संदर्भ स्विचिंग के अतिरिक्त ओवरहेड के साथ) निष्पादित किया जाएगा ।


16
@ एलेक्स, मैंने यह नहीं कहा कि यह व्यावहारिक था, लेकिन यह दर्शाता है कि कैसे परिभाषित और स्पॉन थ्रेड्स हैं, जो मुझे लगता है कि ओपी चाहता है।
माइकल आरोन सफ़्यान

6
हालांकि यह दिखाता है कि थ्रेड्स को कैसे परिभाषित और स्पॉन करना है, यह वास्तव में समानांतर में सबरेंज को योग नहीं करता है। thread1यह तब तक चलता है जब तक कि मुख्य धागा ब्लॉक नहीं हो जाता है, तब यही बात होती है thread2, फिर मुख्य धागा फिर से शुरू होता है और उन मूल्यों को प्रिंट करता है जो वे संचित करते हैं।
मार्टीन्यू

ऐसा नहीं होना चाहिए super(SummingThread, self).__init__()? जैसा कि stackoverflow.com/a/2197625/806988
जेम्स एंड्रेस

@JamesAndres, यह मानते हुए कि कोई भी "SummingThread" से विरासत में नहीं मिला है, तो कोई भी ठीक काम करता है; इस तरह के मामले सुपर में (SummingThread, आत्म) सिर्फ एक आधुनिक तरीका विधि संकल्प आदेश (एमआरओ) है, जो threading.Thread (और फिर बाद में बुला है में अगली कक्षा को देखने के लिए है init दोनों ही मामलों में उस पर)। आप सही हैं, हालांकि, उस में सुपर () का उपयोग करना वर्तमान पायथन के लिए बेहतर शैली है। सुपर उस समय अपेक्षाकृत हाल ही में था जब मैंने यह उत्तर दिया था, इसलिए सुपर () का उपयोग करने के बजाय सीधे सुपर क्लास को कॉल कर रहा था। हालांकि, सुपर का उपयोग करने के लिए मैं इसे अपडेट करूंगा।
माइकल आरोन सफायन

14
चेतावनी: इस तरह के कार्यों में मल्टीथ्रेडिंग का उपयोग न करें! जैसा कि डेव बेज़ले द्वारा दिखाया गया था: dabeaz.com/python/NewGIL.pdf , 2 सीपीयू पर 2 पीथॉन थ्रेड्स 1 सीपीयू पर 1 थ्रेड पर 1 थ्रेड की तुलना में 2 गुना और 1 सीपीयू पर 2 थ्रेड्स की तुलना में 1.5 थ्रेड के लिए एक सीपीयू-भारी कार्य को ले जाते हैं। यह विचित्र व्यवहार ओएस और अजगर के बीच प्रयासों के गलत समन्वय के कारण है। धागे के लिए एक वास्तविक जीवन का उपयोग मामला I / O भारी कार्य है। उदाहरण के लिए, जब आप नेटवर्क पर रीड / राइट करते हैं, तो सीपीयू को एक थ्रेड में डालने, डेटा को पढ़ने / लिखने के लिए बैकग्राउंड में स्विच करने और दूसरे थ्रेड पर स्विच करने के लिए समझ में आता है, जिसके लिए डेटा प्रोसेस करना होता है।
बोरिस बुर्कोव

98

अन्य लोगों की तरह, सीपीआईएचटी केवल जीआईएल के कारण आई / ओ वेट के लिए थ्रेड्स का उपयोग कर सकता है ।

यदि आप सीपीयू-बाउंड कार्यों के लिए कई कोर से लाभ उठाना चाहते हैं, तो मल्टीप्रोसेसिंग का उपयोग करें :

from multiprocessing import Process

def f(name):
    print 'hello', name

if __name__ == '__main__':
    p = Process(target=f, args=('bob',))
    p.start()
    p.join()

33
क्या आप थोड़ा समझा सकते हैं कि यह क्या करता है?
पंडिता

5
@ पंडिता: कोड एक प्रक्रिया बनाता है, फिर उसे शुरू करता है। इसलिए अब एक साथ दो चीजें हो रही हैं: कार्यक्रम की मुख्य पंक्ति, और वह प्रक्रिया जो लक्ष्य, fकार्य के साथ शुरू हो रही है । समानांतर में, मुख्य कार्यक्रम अब बस बाहर निकलने की प्रक्रिया का इंतजार कर रहा है, joinइसके साथ जुड़ा हुआ है। यदि मुख्य भाग बस बाहर निकलता है, तो उपप्रकार पूरा होने के लिए नहीं चल सकता है या नहीं, इसलिए joinहमेशा ऐसा करने की सिफारिश की जाती है।
जॉन्हॉट्सॉल

1
एक विस्तृत जवाब जिसमें mapफ़ंक्शन शामिल है: stackoverflow.com/a/28463266/2327328
philshem

2
@philshem सावधान रहें बी / सी आपके द्वारा पोस्ट किए गए लिंक थ्रेड का एक पूल (नहीं प्रक्रियाओं) का उपयोग कर रहा है जैसा कि यहां उल्लेख किया गया है stackoverflow.com/questions/26432411/… । हालाँकि, यह उत्तर एक प्रक्रिया का उपयोग कर रहा है। मैं इस सामान के लिए नया हूं, लेकिन ऐसा लगता है कि (जीआईएल के कारण) आपको केवल पायथन में मल्टीथ्रेडिंग का उपयोग करते समय विशिष्ट परिस्थितियों में प्रदर्शन लाभ मिलेगा। हालाँकि, प्रक्रियाओं के एक पूल का उपयोग करके एक प्रक्रिया पर 1 से अधिक कोर काम करके मल्टीकोर प्रोसेसर का लाभ ले सकते हैं।
user3731622

3
यह वास्तव में उपयोगी कुछ करने और कई सीपीयू कोर का लाभ उठाने के लिए सबसे अच्छा जवाब है
फ्रोबोट

92

बस एक नोट: सूत्रण के लिए कतार की आवश्यकता नहीं है।

यह सबसे सरल उदाहरण है जिसकी मैं कल्पना कर सकता हूं कि 10 प्रक्रियाएं समवर्ती रूप से चल रही हैं।

import threading
from random import randint
from time import sleep


def print_number(number):

    # Sleeps a random 1 to 10 seconds
    rand_int_var = randint(1, 10)
    sleep(rand_int_var)
    print "Thread " + str(number) + " slept for " + str(rand_int_var) + " seconds"

thread_list = []

for i in range(1, 10):

    # Instantiates the thread
    # (i) does not make a sequence, so (i,)
    t = threading.Thread(target=print_number, args=(i,))
    # Sticks the thread in a list so that it remains accessible
    thread_list.append(t)

# Starts threads
for thread in thread_list:
    thread.start()

# This blocks the calling thread until the thread whose join() method is called is terminated.
# From http://docs.python.org/2/library/threading.html#thread-objects
for thread in thread_list:
    thread.join()

# Demonstrates that the main process waited for threads to complete
print "Done"

3
अंतिम उद्धरण जोड़ें "इसे पूरा करने के लिए किया गया" प्रिंट "
iChux

1
मुझे यह उदाहरण मार्टेली से बेहतर लगता है, इसके साथ खेलना आसान है। हालांकि, मैं सुझाव दूंगा कि प्रिंटनंबर निम्नलिखित करें, इसे थोड़ा स्पष्ट करने के लिए कि क्या चल रहा है: इसे सोने से पहले एक चर के लिए रैंडिंट को सहेजना चाहिए, और फिर प्रिंट को "थ्रेड" + str कहने के लिए बदलना चाहिए संख्या) + + theRandintVariable + "सेकंड" "के लिए सोया"
Nickolai

क्या यह जानने का कोई तरीका है कि प्रत्येक धागा कब समाप्त हो गया है?
मैट

1
@ मैट कुछ ऐसा करने के कुछ तरीके हैं, लेकिन यह आपकी आवश्यकताओं पर निर्भर करेगा। एक तरीका एक सिंगलटन या कुछ अन्य सार्वजनिक रूप से सुलभ चर को अपडेट करना होगा जो थोड़ी देर के लूप में देखा जा रहा है और थ्रेड के अंत में अपडेट किया गया है।
डगलस एडम्स

2
दूसरे forलूप की आवश्यकता नहीं है , आप thread.start()पहले लूप में कॉल कर सकते हैं ।
मार्क मिशिन

49

एलेक्स मार्टेली के जवाब से मुझे मदद मिली। हालांकि, यहां एक संशोधित संस्करण है जो मुझे लगा कि अधिक उपयोगी था (कम से कम मेरे लिए)।

अपडेट किया गया: पायथन 2 और पायथन 3 दोनों में काम करता है

try:
    # For Python 3
    import queue
    from urllib.request import urlopen
except:
    # For Python 2 
    import Queue as queue
    from urllib2 import urlopen

import threading

worker_data = ['http://google.com', 'http://yahoo.com', 'http://bing.com']

# Load up a queue with your data. This will handle locking
q = queue.Queue()
for url in worker_data:
    q.put(url)

# Define a worker function
def worker(url_queue):
    queue_full = True
    while queue_full:
        try:
            # Get your data off the queue, and do some work
            url = url_queue.get(False)
            data = urlopen(url).read()
            print(len(data))

        except queue.Empty:
            queue_full = False

# Create as many threads as you want
thread_count = 5
for i in range(thread_count):
    t = threading.Thread(target=worker, args = (q,))
    t.start()

6
सिर्फ अपवाद पर ही क्यों नहीं?
स्टावरोस कोरोकिथिस

1
आप सिर्फ व्यक्तिगत पसंद कर सकते हैं
जिमजेटी

1
मैंने कोड नहीं चलाया है, लेकिन क्या आपको थ्रेड्स को निष्क्रिय करने की आवश्यकता नहीं है? मुझे लगता है कि उस आखिरी-लूप के बाद, आपका प्रोग्राम बाहर निकल सकता है - कम से कम यह होना चाहिए क्योंकि यह है कि थ्रेड कैसे काम करना चाहिए। मुझे लगता है कि एक बेहतर दृष्टिकोण कार्यकर्ता डेटा को कतार में नहीं रखता है, लेकिन आउटपुट को एक कतार में रखता है क्योंकि तब आपके पास एक मेनलूप हो सकता है जो न केवल श्रमिकों से कतार में आने वाली जानकारी को संभालता है , बल्कि अब यह भी नहीं फैल रहा है, और आप जानते हैं कि यह समय से पहले बाहर नहीं निकलेगा।
dylnmc

1
@dylnmc, यह मेरे उपयोग के मामले के बाहर है (मेरी इनपुट कतार पूर्वनिर्धारित है)। यदि आप अपने मार्ग पर जाना चाहते हैं, तो मैं अजवाइन
दूंगा

@JimJty क्या आप जानते हैं कि मुझे यह त्रुटि क्यों हो रही है: import Queue ModuleNotFoundError: No module named 'Queue'मैं अजगर 3.6.5 चला रहा हूं। कुछ पोस्टों में उल्लेख है कि अजगर 3.6.5 में है, queueलेकिन जब भी मैं इसे बदलता हूं, तब भी काम नहीं करता है
user9371654

25

किसी फ़ंक्शन को देखते हुए f, इसे इस तरह से थ्रेड करें:

import threading
threading.Thread(target=f).start()

से तर्क पारित करना f

threading.Thread(target=f, args=(a,b,c)).start()

यह बहुत सीधा है। जब आप उनके साथ संपन्न होते हैं, तो आप यह कैसे सुनिश्चित कर सकते हैं कि धागे बंद हों?
कैमेरोनोयटायलर

जहां तक ​​मैं इसे समझता हूं, जब फ़ंक्शन बाहर निकलता है तो Threadऑब्जेक्ट साफ हो जाता है। डॉक्स देखें । एक ऐसी is_alive()विधि है जिसका उपयोग आप किसी थ्रेड को जांचने के लिए कर सकते हैं।
स्टारफ्री

मैंने is_aliveविधि देखी , लेकिन मैं यह पता नहीं लगा सका कि इसे धागे पर कैसे लागू किया जाए। मैंने असाइन करने की कोशिश की thread1=threading.Thread(target=f).start()और फिर इसके साथ जांच की thread1.is_alive(), लेकिन इसके साथ thread1आबादी है None, इसलिए वहां कोई भाग्य नहीं है। क्या आपको पता है कि धागे तक पहुंचने का कोई और तरीका है?
कैमरूनोयट्रायलर

4
आपको थ्रेड ऑब्जेक्ट को एक वैरिएबल पर असाइन करने की आवश्यकता है और फिर इसे उस वैरिएबल का उपयोग करके शुरू करें: thread1=threading.Thread(target=f)उसके बाद thread1.start()। तब आप कर सकते हैं thread1.is_alive()
स्टारफ्री

1
वह काम किया। और हाँ, फ़ंक्शन से बाहर निकलते ही thread1.is_alive()रिटर्न के साथ परीक्षण False
कैमेरोनोयरटायलर

25

मुझे यह बहुत उपयोगी लगा: कोर के रूप में कई थ्रेड्स बनाएं और उन्हें कार्यों की एक (बड़ी) संख्या निष्पादित करें (इस मामले में, शेल प्रोग्राम को कॉल करना):

import Queue
import threading
import multiprocessing
import subprocess

q = Queue.Queue()
for i in range(30): # Put 30 tasks in the queue
    q.put(i)

def worker():
    while True:
        item = q.get()
        # Execute a task: call a shell program and wait until it completes
        subprocess.call("echo " + str(item), shell=True)
        q.task_done()

cpus = multiprocessing.cpu_count() # Detect number of cores
print("Creating %d threads" % cpus)
for i in range(cpus):
     t = threading.Thread(target=worker)
     t.daemon = True
     t.start()

q.join() # Block until all tasks are done

@shavenwarthog सुनिश्चित करें कि "cpus" चर को किसी की जरूरतों के आधार पर समायोजित किया जा सकता है। वैसे भी, सबप्रोसेस कॉल उपप्रकारों को फैलाएगी और इन्हें ओएस द्वारा सीपस आवंटित किया जाएगा (अजगर की "मूल प्रक्रिया" का अर्थ उपप्रोसेस के लिए "समान सीपीयू" नहीं है)।
डॉल्फिन

2
आप सही हैं, "धागे के बारे में मेरी टिप्पणी उसी सीपीयू पर शुरू की गई है, जब मूल प्रक्रिया" गलत है। उत्तर के लिए धन्यवाद!
जॉन्हॉट्सॉल

1
शायद यह ध्यान देने योग्य है कि मल्टीथ्रेडिंग के विपरीत जो समान मेमोरी स्पेस का उपयोग करता है, मल्टीप्रोसेसिंग चर / डेटा को आसानी से साझा नहीं कर सकता है। हालांकि +1।
काल्पनिक जूल 23'14

22

पायथन 3 में समानांतर कार्यों को शुरू करने की सुविधा है । इससे हमारा काम आसान हो जाता है।

इसमें थ्रेड पूलिंग और प्रोसेस पूलिंग है

निम्नलिखित एक अंतर्दृष्टि देता है:

ThreadPoolExecutor उदाहरण ( स्रोत )

import concurrent.futures
import urllib.request

URLS = ['http://www.foxnews.com/',
        'http://www.cnn.com/',
        'http://europe.wsj.com/',
        'http://www.bbc.co.uk/',
        'http://some-made-up-domain.com/']

# Retrieve a single page and report the URL and contents
def load_url(url, timeout):
    with urllib.request.urlopen(url, timeout=timeout) as conn:
        return conn.read()

# We can use a with statement to ensure threads are cleaned up promptly
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
    # Start the load operations and mark each future with its URL
    future_to_url = {executor.submit(load_url, url, 60): url for url in URLS}
    for future in concurrent.futures.as_completed(future_to_url):
        url = future_to_url[future]
        try:
            data = future.result()
        except Exception as exc:
            print('%r generated an exception: %s' % (url, exc))
        else:
            print('%r page is %d bytes' % (url, len(data)))

ProcessPoolExecutor ( स्रोत )

import concurrent.futures
import math

PRIMES = [
    112272535095293,
    112582705942171,
    112272535095293,
    115280095190773,
    115797848077099,
    1099726899285419]

def is_prime(n):
    if n % 2 == 0:
        return False

    sqrt_n = int(math.floor(math.sqrt(n)))
    for i in range(3, sqrt_n + 1, 2):
        if n % i == 0:
            return False
    return True

def main():
    with concurrent.futures.ProcessPoolExecutor() as executor:
        for number, prime in zip(PRIMES, executor.map(is_prime, PRIMES)):
            print('%d is prime: %s' % (number, prime))

if __name__ == '__main__':
    main()

18

प्रज्वलन नए का उपयोग concurrent.futures मॉड्यूल

def sqr(val):
    import time
    time.sleep(0.1)
    return val * val

def process_result(result):
    print(result)

def process_these_asap(tasks):
    import concurrent.futures

    with concurrent.futures.ProcessPoolExecutor() as executor:
        futures = []
        for task in tasks:
            futures.append(executor.submit(sqr, task))

        for future in concurrent.futures.as_completed(futures):
            process_result(future.result())
        # Or instead of all this just do:
        # results = executor.map(sqr, tasks)
        # list(map(process_result, results))

def main():
    tasks = list(range(10))
    print('Processing {} tasks'.format(len(tasks)))
    process_these_asap(tasks)
    print('Done')
    return 0

if __name__ == '__main__':
    import sys
    sys.exit(main())

निष्पादक दृष्टिकोण उन सभी से परिचित हो सकता है जिन्होंने पहले जावा के साथ अपने हाथों को गंदा कर दिया था।

एक साइड नोट पर भी: ब्रह्मांड को सुरक्षित रखने के लिए, यदि आप withसंदर्भ का उपयोग नहीं करते हैं, तो अपने पूल / निष्पादकों को बंद करना न भूलें (जो कि आपके लिए ऐसा करता है)


17

मेरे लिए, सूत्रण के लिए सही उदाहरण अतुल्यकालिक घटनाओं की निगरानी कर रहा है। इस कोड को देखें।

# thread_test.py
import threading
import time

class Monitor(threading.Thread):
    def __init__(self, mon):
        threading.Thread.__init__(self)
        self.mon = mon

    def run(self):
        while True:
            if self.mon[0] == 2:
                print "Mon = 2"
                self.mon[0] = 3;

आप IPython सत्र खोलकर और कुछ ऐसा करके इस कोड के साथ खेल सकते हैं:

>>> from thread_test import Monitor
>>> a = [0]
>>> mon = Monitor(a)
>>> mon.start()
>>> a[0] = 2
Mon = 2
>>>a[0] = 2
Mon = 2

कुछ मिनट तक प्रतीक्षा करें

>>> a[0] = 2
Mon = 2

1
गुण: 'मॉनिटर' ऑब्जेक्ट में 'स्टॉप' की कोई विशेषता नहीं है?
पंडिता

5
क्या आप अपनी घटना के होने की प्रतीक्षा करते हुए सीपीयू चक्रों को नष्ट नहीं कर रहे हैं? हमेशा एक बहुत व्यावहारिक बात करने के लिए नहीं।
मोगुल

3
जैसे मोगुल कहता है, यह लगातार क्रियान्वित होगा। कम से कम आप कम नींद में जोड़ सकते हैं, नींद (0.1) कह सकते हैं, जो संभवतः इस तरह के एक सरल उदाहरण पर सीपीयू उपयोग को काफी कम कर देगा।
काल्पनिक जूल

3
यह एक भयानक उदाहरण है, एक कोर बर्बाद कर रहा है। बहुत कम से कम एक नींद जोड़ें लेकिन उचित समाधान कुछ सिग्नलिंग-तंत्र का उपयोग करना है।
प्योरव्यू

16

अधिकांश प्रलेखन और ट्यूटोरियल पायथन Threadingऔर Queueमॉड्यूल का उपयोग करते हैं , और वे शुरुआती के लिए भारी लग सकते हैं।

शायद concurrent.futures.ThreadPoolExecutorपायथन 3 के मॉड्यूल पर विचार करें ।

withक्लॉज और लिस्ट कॉम्प्रिहेंशन के साथ मिलकर यह एक वास्तविक आकर्षण हो सकता है।

from concurrent.futures import ThreadPoolExecutor, as_completed

def get_url(url):
    # Your actual program here. Using threading.Lock() if necessary
    return ""

# List of URLs to fetch
urls = ["url1", "url2"]

with ThreadPoolExecutor(max_workers = 5) as executor:

    # Create threads
    futures = {executor.submit(get_url, url) for url in urls}

    # as_completed() gives you the threads once finished
    for f in as_completed(futures):
        # Get the results
        rs = f.result()

15

मैंने यहां बहुत सारे उदाहरण देखे जहां कोई वास्तविक कार्य नहीं किया जा रहा था, और वे ज्यादातर सीपीयू-बाउंड थे। यहां एक सीपीयू-बाउंड कार्य का एक उदाहरण है जो 10 मिलियन और 10.05 मिलियन के बीच सभी प्रमुख संख्याओं की गणना करता है। मैंने यहाँ सभी चार विधियों का उपयोग किया है:

import math
import timeit
import threading
import multiprocessing
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor


def time_stuff(fn):
    """
    Measure time of execution of a function
    """
    def wrapper(*args, **kwargs):
        t0 = timeit.default_timer()
        fn(*args, **kwargs)
        t1 = timeit.default_timer()
        print("{} seconds".format(t1 - t0))
    return wrapper

def find_primes_in(nmin, nmax):
    """
    Compute a list of prime numbers between the given minimum and maximum arguments
    """
    primes = []

    # Loop from minimum to maximum
    for current in range(nmin, nmax + 1):

        # Take the square root of the current number
        sqrt_n = int(math.sqrt(current))
        found = False

        # Check if the any number from 2 to the square root + 1 divides the current numnber under consideration
        for number in range(2, sqrt_n + 1):

            # If divisible we have found a factor, hence this is not a prime number, lets move to the next one
            if current % number == 0:
                found = True
                break

        # If not divisible, add this number to the list of primes that we have found so far
        if not found:
            primes.append(current)

    # I am merely printing the length of the array containing all the primes, but feel free to do what you want
    print(len(primes))

@time_stuff
def sequential_prime_finder(nmin, nmax):
    """
    Use the main process and main thread to compute everything in this case
    """
    find_primes_in(nmin, nmax)

@time_stuff
def threading_prime_finder(nmin, nmax):
    """
    If the minimum is 1000 and the maximum is 2000 and we have four workers,
    1000 - 1250 to worker 1
    1250 - 1500 to worker 2
    1500 - 1750 to worker 3
    1750 - 2000 to worker 4
    so let’s split the minimum and maximum values according to the number of workers
    """
    nrange = nmax - nmin
    threads = []
    for i in range(8):
        start = int(nmin + i * nrange/8)
        end = int(nmin + (i + 1) * nrange/8)

        # Start the thread with the minimum and maximum split up to compute
        # Parallel computation will not work here due to the GIL since this is a CPU-bound task
        t = threading.Thread(target = find_primes_in, args = (start, end))
        threads.append(t)
        t.start()

    # Don’t forget to wait for the threads to finish
    for t in threads:
        t.join()

@time_stuff
def processing_prime_finder(nmin, nmax):
    """
    Split the minimum, maximum interval similar to the threading method above, but use processes this time
    """
    nrange = nmax - nmin
    processes = []
    for i in range(8):
        start = int(nmin + i * nrange/8)
        end = int(nmin + (i + 1) * nrange/8)
        p = multiprocessing.Process(target = find_primes_in, args = (start, end))
        processes.append(p)
        p.start()

    for p in processes:
        p.join()

@time_stuff
def thread_executor_prime_finder(nmin, nmax):
    """
    Split the min max interval similar to the threading method, but use a thread pool executor this time.
    This method is slightly faster than using pure threading as the pools manage threads more efficiently.
    This method is still slow due to the GIL limitations since we are doing a CPU-bound task.
    """
    nrange = nmax - nmin
    with ThreadPoolExecutor(max_workers = 8) as e:
        for i in range(8):
            start = int(nmin + i * nrange/8)
            end = int(nmin + (i + 1) * nrange/8)
            e.submit(find_primes_in, start, end)

@time_stuff
def process_executor_prime_finder(nmin, nmax):
    """
    Split the min max interval similar to the threading method, but use the process pool executor.
    This is the fastest method recorded so far as it manages process efficiently + overcomes GIL limitations.
    RECOMMENDED METHOD FOR CPU-BOUND TASKS
    """
    nrange = nmax - nmin
    with ProcessPoolExecutor(max_workers = 8) as e:
        for i in range(8):
            start = int(nmin + i * nrange/8)
            end = int(nmin + (i + 1) * nrange/8)
            e.submit(find_primes_in, start, end)

def main():
    nmin = int(1e7)
    nmax = int(1.05e7)
    print("Sequential Prime Finder Starting")
    sequential_prime_finder(nmin, nmax)
    print("Threading Prime Finder Starting")
    threading_prime_finder(nmin, nmax)
    print("Processing Prime Finder Starting")
    processing_prime_finder(nmin, nmax)
    print("Thread Executor Prime Finder Starting")
    thread_executor_prime_finder(nmin, nmax)
    print("Process Executor Finder Starting")
    process_executor_prime_finder(nmin, nmax)

main()

यहाँ मेरे मैक ओएस एक्स चार-कोर मशीन पर परिणाम हैं

Sequential Prime Finder Starting
9.708213827005238 seconds
Threading Prime Finder Starting
9.81836523200036 seconds
Processing Prime Finder Starting
3.2467174359990167 seconds
Thread Executor Prime Finder Starting
10.228896902000997 seconds
Process Executor Finder Starting
2.656402041000547 seconds

1
@ TheUnfunCat कोई प्रक्रिया निष्पादक नहीं है जो सीपीयू बाध्य कार्यों के लिए थ्रेडिंग से बेहतर है
PirateApp

1
महान जवाब दोस्त। मैं यह पुष्टि कर सकता हूं कि विंडोज पर पायथन 3.6 में (कम से कम) थ्रेडपूल एक्सक्यूटर सीपीयू-भारी कार्यों के लिए कुछ भी अच्छा नहीं करता है। यह संगणना के लिए कोर का उपयोग नहीं कर रहा है। जबकि ProcessPoolExecutor EVERY प्रक्रिया में डेटा को कॉपी करता है, जो इसे स्पैन करता है, यह बड़े मैट्रिसेस के लिए घातक है।
अनातोली अलेक्सेव

1
बहुत उपयोगी उदाहरण है, लेकिन मुझे समझ नहीं आता कि यह कैसे काम करता है। हम एक की जरूरत है if __name__ == '__main__':अन्यथा माप spawns ही है और प्रिंट मुख्य कॉल करने से पहले, एक प्रयास किया गया है से पहले एक नई प्रक्रिया शुरू करने के लिए ...
Stein

1
@ हालांकि मुझे विश्वास है कि यह केवल विंडोज पर एक मुद्दा है, हालांकि।
AMC

12

यहां थ्रेडिंग का उपयोग करके CSV आयात का बहुत ही सरल उदाहरण दिया गया है । (लाइब्रेरी समावेशन अलग उद्देश्य के लिए भिन्न हो सकते हैं।)

सहायक कार्य:

from threading import Thread
from project import app
import csv


def import_handler(csv_file_name):
    thr = Thread(target=dump_async_csv_data, args=[csv_file_name])
    thr.start()

def dump_async_csv_data(csv_file_name):
    with app.app_context():
        with open(csv_file_name) as File:
            reader = csv.DictReader(File)
            for row in reader:
                # DB operation/query

ड्राइवर समारोह:

import_handler(csv_file_name)

9

मैं एक सरल उदाहरण और स्पष्टीकरण के साथ योगदान करना चाहता हूं, जब मुझे इस समस्या से निपटने के लिए उपयोगी पाया गया है।

इस उत्तर में आपको पायथन के जीआईएल (वैश्विक दुभाषिया लॉक) के बारे में कुछ जानकारी मिलेगी और एक सरल दिन-प्रतिदिन का उदाहरण मल्टीप्रोसेसिंग डमी का उपयोग करके लिखा जाएगा और साथ ही कुछ सरल बेंचमार्क भी।

ग्लोबल इंटरप्रेटर लॉक (GIL)

पायथन शब्द के ट्रुस्ट अर्थ में मल्टी-थ्रेडिंग की अनुमति नहीं देता है। इसमें एक मल्टी-थ्रेडिंग पैकेज है, लेकिन अगर आप अपने कोड को गति देने के लिए मल्टी-थ्रेड बनाना चाहते हैं, तो आमतौर पर इसका उपयोग करने के लिए एक अच्छा विचार नहीं है।

पायथन में एक कंस्ट्रक्शन है जिसे ग्लोबल इंटरप्रेटर लॉक (GIL) कहा जाता है। जीआईएल यह सुनिश्चित करता है कि आपके किसी भी एक समय पर केवल एक 'थ्रेड' निष्पादित हो सकता है। एक धागा GIL का अधिग्रहण करता है, थोड़ा काम करता है, फिर अगले धागे पर GIL पास करता है।

यह बहुत जल्दी से होता है ताकि मानव आंख को यह महसूस हो सके कि आपके धागे समानांतर में निष्पादित हो रहे हैं, लेकिन वे वास्तव में बस एक ही सीपीयू कोर का उपयोग करके मोड़ ले रहे हैं।

यह सब GIL पास निष्पादन के लिए ओवरहेड जोड़ता है। इसका मतलब है कि यदि आप अपने कोड को तेजी से चलाना चाहते हैं तो थ्रेडिंग पैकेज का उपयोग करना अक्सर अच्छा विचार नहीं होता है।

पायथन के थ्रेडिंग पैकेज का उपयोग करने के कारण हैं। यदि आप कुछ चीजों को एक साथ चलाना चाहते हैं, और दक्षता चिंता का विषय नहीं है, तो यह पूरी तरह से ठीक है और सुविधाजनक है। या यदि आप ऐसा कोड चला रहे हैं, जिसके लिए कुछ (जैसे I / O) प्रतीक्षा करनी पड़ती है, तो यह बहुत मायने रख सकता है। लेकिन थ्रेडिंग लाइब्रेरी आपको अतिरिक्त सीपीयू कोर का उपयोग नहीं करने देगी।

मल्टी-थ्रेडिंग को ऑपरेटिंग सिस्टम (मल्टी-प्रोसेसिंग करके) के लिए आउटसोर्स किया जा सकता है, और कुछ बाहरी एप्लिकेशन जो आपके पायथन कोड (उदाहरण के लिए, स्पार्क या हडोप ) को कॉल करते हैं , या कुछ कोड जिसे आपका पायथन कोड कॉल करता है (उदाहरण के लिए) - अपने पायथन कोड को एक C फ़ंक्शन कहें जो महंगा बहु-थ्रेडेड सामान करता है)।

क्यों यह मामला

क्योंकि बहुत से लोग जीआईएल क्या है यह जानने से पहले अपने फैंसी पायथन मल्टी थ्रेडेड कोड में अड़चन खोजने की कोशिश में बहुत समय बिताते हैं।

यह जानकारी स्पष्ट हो जाने के बाद, मेरा कोड यहाँ है:

#!/bin/python
from multiprocessing.dummy import Pool
from subprocess import PIPE,Popen
import time
import os

# In the variable pool_size we define the "parallelness".
# For CPU-bound tasks, it doesn't make sense to create more Pool processes
# than you have cores to run them on.
#
# On the other hand, if you are using I/O-bound tasks, it may make sense
# to create a quite a few more Pool processes than cores, since the processes
# will probably spend most their time blocked (waiting for I/O to complete).
pool_size = 8

def do_ping(ip):
    if os.name == 'nt':
        print ("Using Windows Ping to " + ip)
        proc = Popen(['ping', ip], stdout=PIPE)
        return proc.communicate()[0]
    else:
        print ("Using Linux / Unix Ping to " + ip)
        proc = Popen(['ping', ip, '-c', '4'], stdout=PIPE)
        return proc.communicate()[0]


os.system('cls' if os.name=='nt' else 'clear')
print ("Running using threads\n")
start_time = time.time()
pool = Pool(pool_size)
website_names = ["www.google.com","www.facebook.com","www.pinterest.com","www.microsoft.com"]
result = {}
for website_name in website_names:
    result[website_name] = pool.apply_async(do_ping, args=(website_name,))
pool.close()
pool.join()
print ("\n--- Execution took {} seconds ---".format((time.time() - start_time)))

# Now we do the same without threading, just to compare time
print ("\nRunning NOT using threads\n")
start_time = time.time()
for website_name in website_names:
    do_ping(website_name)
print ("\n--- Execution took {} seconds ---".format((time.time() - start_time)))

# Here's one way to print the final output from the threads
output = {}
for key, value in result.items():
    output[key] = value.get()
print ("\nOutput aggregated in a Dictionary:")
print (output)
print ("\n")

print ("\nPretty printed output: ")
for key, value in output.items():
    print (key + "\n")
    print (value)

7

यहां एक सरल उदाहरण के साथ मल्टी थ्रेडिंग है जो सहायक होगा। आप इसे चला सकते हैं और आसानी से समझ सकते हैं कि पायथन में मल्टी थ्रेडिंग कैसे काम कर रही है। मैंने अन्य थ्रेड्स तक पहुंच को रोकने के लिए एक लॉक का उपयोग किया जब तक कि पिछले थ्रेड्स ने अपना काम खत्म नहीं किया। इस लाइन के उपयोग के द्वारा,

tLock = threading.BoundedSemaphore (मान = 4)

आप एक समय में कई प्रक्रियाओं की अनुमति दे सकते हैं और शेष थ्रेड्स पर पकड़ बनाए रख सकते हैं जो बाद की पिछली प्रक्रियाओं के बाद या बाद में चलेंगे।

import threading
import time

#tLock = threading.Lock()
tLock = threading.BoundedSemaphore(value=4)
def timer(name, delay, repeat):
    print  "\r\nTimer: ", name, " Started"
    tLock.acquire()
    print "\r\n", name, " has the acquired the lock"
    while repeat > 0:
        time.sleep(delay)
        print "\r\n", name, ": ", str(time.ctime(time.time()))
        repeat -= 1

    print "\r\n", name, " is releaseing the lock"
    tLock.release()
    print "\r\nTimer: ", name, " Completed"

def Main():
    t1 = threading.Thread(target=timer, args=("Timer1", 2, 5))
    t2 = threading.Thread(target=timer, args=("Timer2", 3, 5))
    t3 = threading.Thread(target=timer, args=("Timer3", 4, 5))
    t4 = threading.Thread(target=timer, args=("Timer4", 5, 5))
    t5 = threading.Thread(target=timer, args=("Timer5", 0.1, 5))

    t1.start()
    t2.start()
    t3.start()
    t4.start()
    t5.start()

    print "\r\nMain Complete"

if __name__ == "__main__":
    Main()

5

इस पोस्ट से उधार लेने के साथ हम मल्टीथ्रेडिंग, मल्टीप्रोसेसिंग और एसिंक्स / asyncioऔर उनके उपयोग के बीच चयन के बारे में जानते हैं ।

पायथन 3 में समरूपता और समानता के लिए एक नया अंतर्निहित पुस्तकालय है: समवर्ती

इसलिए मैं चार कार्यों (अर्थात .sleep()विधि) को Threading-Poolढंग से चलाने के लिए एक प्रयोग के माध्यम से प्रदर्शित करूँगा :

from concurrent.futures import ThreadPoolExecutor, as_completed
from time import sleep, time

def concurrent(max_worker=1):
    futures = []

    tick = time()
    with ThreadPoolExecutor(max_workers=max_worker) as executor:
        futures.append(executor.submit(sleep, 2))  # Two seconds sleep
        futures.append(executor.submit(sleep, 1))
        futures.append(executor.submit(sleep, 7))
        futures.append(executor.submit(sleep, 3))

        for future in as_completed(futures):
            if future.result() is not None:
                print(future.result())

    print('Total elapsed time by {} workers:'.format(max_worker), time()-tick)

concurrent(5)
concurrent(4)
concurrent(3)
concurrent(2)
concurrent(1)

आउटपुट:

Total elapsed time by 5 workers: 7.007831811904907
Total elapsed time by 4 workers: 7.007944107055664
Total elapsed time by 3 workers: 7.003149509429932
Total elapsed time by 2 workers: 8.004627466201782
Total elapsed time by 1 workers: 13.013478994369507

[ नोट ]:

  • जैसा कि आप उपरोक्त परिणामों में देख सकते हैं, उन चार कार्यों के लिए सबसे अच्छा मामला 3 श्रमिकों का था ।
  • आप मैं के बजाय एक प्रक्रिया काम है, तो / ओ बाध्य या अवरुद्ध ( multiprocessingबनाम threading) आप को बदल सकता है ThreadPoolExecutorके लिए ProcessPoolExecutor

4

पिछले समाधानों में से कोई भी वास्तव में मेरे जीएनयू / लिनक्स सर्वर (जहां मेरे पास व्यवस्थापक अधिकार नहीं है) पर कई कोर का उपयोग किया गया था। वे बस एक ही कोर पर चले गए।

मैंने os.forkकई प्रक्रियाओं को स्पॉन करने के लिए निचले स्तर के इंटरफ़ेस का उपयोग किया । यह वह कोड है जो मेरे लिए काम करता है:

from os import fork

values = ['different', 'values', 'for', 'threads']

for i in range(len(values)):
    p = fork()
    if p == 0:
        my_function(values[i])
        break

2
import threading
import requests

def send():

  r = requests.get('https://www.stackoverlow.com')

thread = []
t = threading.Thread(target=send())
thread.append(t)
t.start()

1
@sP_ मैं अनुमान लगा रहा हूं क्योंकि तब आपके पास थ्रेड ऑब्जेक्ट हैं ताकि आप उनके खत्म होने का इंतजार कर सकें।
अलेक्जेंडर मकरगी

1
t = थ्रेडिंग। थ्रेड (लक्ष्य = भेजें) () टी होना चाहिए। थ्रेडिंग। थ्रेड (लक्ष्य = भेजें)
TRiNE

मैं इस उत्तर को अस्वीकार कर रहा हूं क्योंकि यह एक गंभीर अशुद्धि से युक्त होने के अलावा मौजूदा उत्तरों में कैसे सुधार करता है, इसकी व्याख्या प्रदान नहीं करता है।
जूल्स २
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.