आप जो खोज रहे हैं वह निर्माता / उपभोक्ता पैटर्न है
मूल सूत्रण उदाहरण
यहां थ्रेडिंग मॉड्यूल (मल्टीप्रोसेसिंग के बजाय) का उपयोग करके एक बुनियादी उदाहरण दिया गया है
import threading
import Queue
import sys
def do_work(in_queue, out_queue):
while True:
item = in_queue.get()
result = item
out_queue.put(result)
in_queue.task_done()
if __name__ == "__main__":
work = Queue.Queue()
results = Queue.Queue()
total = 20
for i in xrange(4):
t = threading.Thread(target=do_work, args=(work, results))
t.daemon = True
t.start()
for i in xrange(total):
work.put(i)
work.join()
for i in xrange(total):
print results.get()
sys.exit()
आप थ्रेड के साथ फ़ाइल ऑब्जेक्ट साझा नहीं करेंगे। आप आपूर्ति करके उनके लिए काम का उत्पादन करेंगे डेटा की लाइनों के साथ कतार । फिर प्रत्येक थ्रेड एक लाइन उठाएगा, इसे प्रोसेस करेगा, और फिर इसे कतार में लौटाएगा।
डेटा साझा करने के लिए मल्टीप्रोसेसिंग मॉड्यूल में निर्मित कुछ और उन्नत सुविधाएं हैं , जैसे सूचियां और विशेष प्रकार की कतार । मल्टीप्रोसेसिंग बनाम थ्रेड्स का उपयोग करने के लिए ट्रेड-ऑफ़ हैं और यह इस बात पर निर्भर करता है कि आपका काम सीपीयू बाध्य है या आईओ बाध्य है।
बेसिक मल्टीप्रोसेसिंग।पूल उदाहरण
यहाँ एक बहुप्रतिष्ठित पूल का वास्तव में मूल उदाहरण है
from multiprocessing import Pool
def process_line(line):
return "FOO: %s" % line
if __name__ == "__main__":
pool = Pool(4)
with open('file.txt') as source_file:
results = pool.map(process_line, source_file, 4)
print results
एक पूल एक सुविधा वस्तु है जो अपनी प्रक्रियाओं का प्रबंधन करता है। चूंकि एक खुली फ़ाइल इसकी लाइनों पर पुनरावृति कर सकती है, आप इसे पास कर सकते हैं pool.map()
, जो इस पर लूप करेगा और कार्यकर्ता फ़ंक्शन को लाइनें वितरित करेगा। जब यह पूरा हो जाए तो मैप ब्लॉक और रिटर्न कर देता है। ज्ञात हो कि यह एक अति सरलीकृत उदाहरण है, और यह किpool.map()
पूरा करने से पहले एक बार में अपनी पूरी फ़ाइल को मेमोरी में पढ़ने जा रहा है। यदि आपको बड़ी फ़ाइलों की उम्मीद है, तो इसे ध्यान में रखें। निर्माता / उपभोक्ता सेटअप डिजाइन करने के लिए और अधिक उन्नत तरीके हैं।
मैनुअल "पूल" सीमा और रेखा के साथ फिर से छँटाई
यह पूल.मैप का एक मैनुअल उदाहरण है , लेकिन एक बार में एक पूरे चलने योग्य का उपभोग करने के बजाय, आप एक कतार का आकार निर्धारित कर सकते हैं ताकि आप केवल टुकड़े टुकड़े करके इसे जितनी जल्दी हो सके खिला सकें। मैंने लाइन नंबरों को भी जोड़ा ताकि आप उन्हें ट्रैक कर सकें और यदि चाहें तो बाद में उन्हें संदर्भित कर सकें।
from multiprocessing import Process, Manager
import time
import itertools
def do_work(in_queue, out_list):
while True:
item = in_queue.get()
line_no, line = item
if line == None:
return
time.sleep(.5)
result = (line_no, line)
out_list.append(result)
if __name__ == "__main__":
num_workers = 4
manager = Manager()
results = manager.list()
work = manager.Queue(num_workers)
pool = []
for i in xrange(num_workers):
p = Process(target=do_work, args=(work, results))
p.start()
pool.append(p)
with open("source.txt") as f:
iters = itertools.chain(f, (None,)*num_workers)
for num_and_line in enumerate(iters):
work.put(num_and_line)
for p in pool:
p.join()
print sorted(results)