あなたが探しているのは生産者/消費者パターンです
基本的なスレッドの例
これは、(マルチプロセッシングの代わりに)スレッドモジュールを使用した基本的な例です。
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()
ファイルオブジェクトをスレッドと共有することはありません。キューにデータ行を提供することで、彼らのために仕事を生み出します。次に、各スレッドは行を取得して処理し、キューに戻します。
リストや特別な種類のキューなど、データを共有するためにマルチプロセッシングモジュールに組み込まれているより高度な機能がいくつかあります。マルチプロセッシングとスレッドの使用にはトレードオフがあり、作業がCPUバウンドかIOバウンドかによって異なります。
基本的なマルチプロセッシング。プールの例
これがマルチプロセッシングプールの本当に基本的な例です
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()
作業を行う前にファイル全体を一度にメモリに読み込むことに注意してください。大きなファイルが必要な場合は、このことに注意してください。プロデューサー/コンシューマーのセットアップを設計するためのより高度な方法があります。
制限と行の再ソートを伴う手動「プール」
これはPool.mapの手動の例ですが、反復可能ファイル全体を一度に消費する代わりに、キューサイズを設定して、処理可能な速度で1つずつフィードするようにすることができます。また、後で追跡して参照できるように、行番号を追加しました。
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)