线程,多处理

2024-10-01 09:37:11 发布

您现在位置:Python中文网/ 问答频道 /正文

它与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. 我知道代码是肮脏的:(……这是一种干净的方法吗?在

谢谢你们。在


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

这整件事还可以重写得更好,但我只是在给你的东西贴上绷带。我只是把这个和你的东西混在一起。在

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

其次,要编写一个干净的多线程代码,使用decorator可以帮助您,并使其在线程和进程之间切换。在

检查这里的示例decorators async decorator

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

 easy_install decorator

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

相关问题 更多 >