2 つの異なるソリューションを混同しています。
ファイルごとに専用のワーカー スレッドを作成する場合は、何のキューも必要ありません。スレッドプールとファイルのキューを作成する場合は、andをメソッドに渡したくありません。それらをキューの各ジョブに入れたいとします。inpfile
outfile
run
2つの中からどのように選択しますか?最初のほうが明らかに単純ですが、たとえば、コピーするファイルが 1000 個ある場合、最終的に 1000 個のスレッドを作成することになります。これは、作成したいよりも多くのスレッドであり、並列コピーの数よりもはるかに多くのスレッドです。 OSが処理できるようになります。スレッド プールを使用すると、たとえば 8 つのスレッドを作成し、1000 個のジョブをキューに入れることができます。ジョブは必要に応じてスレッドに分散されるため、一度に 8 つのジョブが実行されます。
各ファイル専用のワーカー スレッドであるソリューション 1 から始めましょう。
まず、サブクラス化と結婚していない場合Thread
、ここでそうする理由はまったくありません。target
関数とargs
タプルをデフォルトのコンストラクターに渡すことができます。その後、run
メソッドはtarget(*args)
必要に応じて正確に実行します。そう:
t = threading.Thread(target=workermethod, args=(inpfile, outfile))
それだけです。各スレッドが実行されると、呼び出しworkermethod(inpfile, outfile)
てから終了します。
ただし、何らかの理由でサブクラス化したい場合は可能です。構築時に and を渡すことができます。メソッドThread
は、パラメーターを受け取る代わりにandを使用するように変更されたものになります。このような:inpfile
outfile
run
workermethod
self.inpfile
self.outfile
class ThreadUrl(threading.Thread):
def __init__(self, inpfile, outfile):
threading.Thread.__init__(self)
self.inpfile, self.outfile = inpfile, outfile
def run(self):
f1 = open(self.inpfile,'r')
f2 = open(self.outfile,'w')
x = f1.readlines()
for each in x:
f2.write(each)
f1.close()
f2.close()
いずれにせよ、非常に古いバージョンの Python を扱う必要がない限り、明示的な and の代わりにステートメントを使用し、(不必要にファイル全体をメモリに読み込む) を取り除くwith
ことをお勧めします。open
close
readlines
def run(self):
with open(self.inpfile,'r') as f1, open(self.outfile,'w') as f2:
for line in f1:
f2.write(line)
次に、解決策 2 に進みます: スレッドプールとキュー。
ここでも、サブクラスは必要ありません。物事を行う 2 つの方法の違いは、ソリューション 1 と同じです。ただし、開始したサブクラスの設計に固執すると、次のようなものが必要になります。
class ThreadUrl(threading.Thread):
def __init__(self,queue):
threading.Thread.__init__(self)
self.queue = queue
def run(self):
while True:
inpfile, outfile = self.queue.get()
workermethod(inpfile, outfile)
次に、単一のスレッドqueue
をすべてのスレッドに渡してスレッドを開始します。
q = queue.Queue
threadpool = [ThreadUrl(q) for i in range(poolsize)]
そして、次のようなジョブを送信します。
q.put((inpfile, outfile))
スレッドプールで本格的な作業を行う場合は、自分で何かをコーディングするのではなく、堅牢で柔軟性があり、シンプルで最適化された実装を使用することを検討することをお勧めします。たとえば、ジョブをキャンセルしたり、キューを適切にシャットダウンしたり、スレッドを 1 つずつ結合する代わりにプール全体に結合したり、バッチ処理やスマートな負荷分散を実行したりしたい場合があります。
Python 3 を使用している場合は、 standard-library を確認する必要がありますThreadPoolExecutor
。Future
Python 2 に行き詰まっている場合、またはsがわからない場合は、モジュールThreadPool
内に隠されているクラスを確認することをお勧めします。multiprocessing
これらの両方には、マルチスレッドからマルチプロセッシングへの切り替えが簡単であるという利点があります (たとえば、IO と共に並列化する必要がある CPU バウンドの作業があることが判明した場合)。PyPI を検索することもできます。他にも優れた実装が複数見つかります。
queue
補足として、モジュール名をシャドウするため、 queue を呼び出したくありません。workermethod
また、実際にはメソッドではなくフリー関数であると呼ばれるものがあると、少し混乱します。
最後に、ファイルをコピーするだけなら、おそらくテキスト モードで読んだり、行単位で読みたいとは思わないでしょう。実際、自分で実装したいとは思わないでしょう。から適切なコピー機能を使用するだけshutil
です。上記の方法のいずれかで非常に簡単にそれを行うことができます。たとえば、これの代わりに:
t = threading.Thread(target=workermethod, args=(inpfile, outfile))
これを行う:
t = threading.Thread(target=shutil.copyfile, args=(inpfile, outfile))
実際、プログラム全体を次のように置き換えることができるようです。
threads = [threading.Thread(target=shutil.copyfile, args=(inpfile, outfile))
for (inpfile, outfile) in zip(filelistread, filelistwrte)]
for thread in threads:
thread.start()
for thread in threads:
thread.join()