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.walk,并且直接以q.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因为它永远不会像你想象的那样做。如果打印机在任何时候清除了结果队列,但线程仍在尝试查找更多,则队列将认为其完成并退出。我用另一个队列代替它作为信号。每个工人在完成后将一个项目放入队列中。然后打印机继续检查它是否可以从完成队列中提取足够的信号以等于启动的工人数量。如果是这样,它将退出。

整个事情仍然可以更好地重写,但我只是在你所拥有的东西上使用创可贴。我只是把它和你所拥有的放在一起。

请注意,您启动整个过程的方式,检查启动路径下的目录,如果只有文件,基本上只会退出。

于 2012-07-09T01:53:45.283 回答
1

第二,编写干净的多线程代码,使用装饰器可以帮助您,并使线程和进程之间的切换更容易。

在这里查看示例装饰器异步装饰器

您可以通过以下方式安装装饰器:

 easy_install decorator

或下载代码,使用python setup.py install

于 2012-07-09T01:44:13.473 回答