线程,多处理错误

时间:2012-07-09 01:25:35

标签: python multithreading

它与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. 我知道代码很脏:(...这是一个干净的方法吗?
  3. 谢谢你们。

2 个答案:

答案 0 :(得分: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,因为它永远不会按照您的想法去做。如果打印机在任何时候清除了结果队列,但线程仍在尝试查找更多,则队列会认为已完成并退出。我替换它的是另一个用作信号的队列。每个工作人员在完成后将项目放入队列中。然后打印机继续检查是否可以从完成队列中提取足够的信号以等于启动的工作量。如果是这样,它将退出。

这整件事情仍然可以更好地重写,但我只是将绑带用于你所拥有的。我只是把它和你的东西一起扔了。

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

答案 1 :(得分:1)

为你的第二个,写一个干净的多线程代码,使用装饰器帮助你,并使它在线程和进程之间切换。

查看此处的示例decorators async decorator

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

 easy_install decorator

或使用python setup.py install

下载代码