0

Windows の finder と同じですが、スレッドを使用して高速化し、

    import os,threading,multiprocessing


    def finder(path,q):
     for x in os.walk(unicode(path)):
      if x[1]:
       for dirname in x[1]:
        if target in dirname.lower():
         q.put(os.path.join(x[0],dirname))
      if x[2]:
       for name in x[2]:
        if target in name.lower():
         q.put(os.path.join(x[0],name))

     q.put(1)

    def printer(q):
     cmd=0
     while 1:
      tmp=q.get()
      if tmp==1:
       cmd += 1
       continue
      if cmd ==thnum:
       break
      print tmp

    if __name__ =="__main__":
     q=multiprocessing.JoinableQueue()
     ini=os.walk(u"C:\\").next()
     thnum=len(ini[1])
     target=raw_input("what you wanna get\n")

     p=multiprocessing.Process(target=printer,args=(q,))
     p.daemon=1
     p.start()

     for i in xrange(thnum):
      t=threading.Thread(target=finder,args=(ini[1][i],q,))
      t.start()
      print i," started"
     q.join()

それが示している

0 開始 1 開始 .... 22 開始

しかし、結果が表示されないので、私の質問は

  1. なぜ結果が表示されないのですか
  2. 私はコードが汚れていることを知っています:(...それはそれを行うためのきれいな方法ですか?

君たちありがとう。

4

2 に答える 2

2

ここには大量の乱雑なコードといくつかのエラーがあります。私が見る主な問題は、スレッドがすぐに から何も生成できずos.walkq.put. これは、各スレッドにフル パスを渡さないためです。ディレクトリ名のみ。ただし、変数にわかりやすい名前を使用しないため、これを知るのは困難です。

クリーンアップされたバージョンは次のとおりです。

import os
import threading
import multiprocessing


def finder(path, q, done):
    for root, dirs, files in os.walk(unicode(path)):
        for dirname in dirs:
            if target in dirname.lower():
                q.put(os.path.join(root,dirname))
        for name in files:
            if target in name.lower():
                q.put(os.path.join(root,name))

    # print "Leaving thread", threading.current_thread()
    done.put(1)

def printer(q,done,worker_count):
    total = 0
    while 1:
        try: done.get_nowait()
        except: pass
        else: total += 1

        if total == worker_count:
            break

        try: tmp=q.get(timeout=1)
        except: pass

        print tmp

if __name__ =="__main__":

    results = multiprocessing.Queue()
    done = multiprocessing.Queue()
    root, dirs, files = os.walk(u"C:\\").next()
    thnum=len(dirs)
    target=raw_input("what you wanna get\n")

    p=multiprocessing.Process(target=printer,args=(results,done,thnum))
    p.start()

    for i in xrange(thnum):
        full_path = os.path.join(root, dirs[i])
        t=threading.Thread(target=finder,args=(full_path, results, done))
        t.start()

    p.join()

各スレッドに送信する前に、メイン ブロックでフル パスを結合する方法を確認してください。を削除しましJoinableQueueた。プリンターが結果キューをクリアしても、スレッドがまだ検索を続けている場合、キューは完了したと判断して終了します。置き換えたのは、シグナルとして使用する別のキューです。各ワーカーは、完了時にアイテムをキューに入れます。次に、プリンターは、起動されたワーカーの数に等しくなるように、done キューから十分なシグナルを取得できるかどうかを確認し続けます。その場合、終了します。

この全体はまだもっとうまく書き直すことができますが、私はあなたが持っているものにバンドエイドを適用しているだけです. 私はこれをあなたが持っていたものと一緒に投げただけです。

開始パスの下のディレクトリをチェックしてプロセス全体を開始する方法は、ファイルしかない場合は基本的に終了することに注意してください。

于 2012-07-09T01:53:45.283 に答える
1

次に、クリーンなマルチスレッド コードを作成するには、デコレータを使用すると、スレッドとプロセスの切り替えが容易になります。

ここで例を確認してくださいデコレーター 非同期デコレーター

次の方法でデコレータをインストールできます。

 easy_install decorator

または、コードをダウンロードして、python setup.py install

于 2012-07-09T01:44:13.473 に答える