Python 线程/队列挂起问题

Python 线程/队列挂起问题,python,multithreading,queue,Python,Multithreading,Queue,新手在这里穿线。在尝试使用线程/队列构建我的第一个脚本时,我从中借用了很多代码: import threading, urllib2 import Queue import sys from PIL import Image import io, sys def avhash(url,queue): if not isinstance(url, Image.Image): try: im = Image.open(url) exc

新手在这里穿线。在尝试使用线程/队列构建我的第一个脚本时,我从中借用了很多代码:

import threading, urllib2
import Queue
import sys
from PIL import Image
import io, sys

def avhash(url,queue):
    if not isinstance(url, Image.Image):
        try:
            im = Image.open(url)
        except IOError:
            fd=urllib2.urlopen(url)
            image_file=io.BytesIO(fd.read())
            im=Image.open(image_file)
            im = im.resize((8, 8), Image.ANTIALIAS).convert('L')
            avg = reduce(lambda x, y: x + y, im.getdata()) / 64.
    hash = reduce(lambda x, (y, z): x | (z << y),
                  enumerate(map(lambda i: 0 if i < avg else 1, im.getdata())),
                  0)

    queue.put({url:hash})
    queue.task_done()

def fetch_parallel(job_list):
    q = Queue.Queue()
    threads = [threading.Thread(target=avhash, args = (job,q)) for job in job_list[0:50]]
    for t in threads:
        t.daemon = True
        t.start()

    for t in threads:
        t.join()
    return [q.get() for _ in xrange(len(job_list))]

在本例中,作业列表是URL的列表。我发现当该列表等于或小于50时,该代码可以正常工作,但当>50时,它将挂起。关于线程是如何工作的,肯定有一些我根本不了解的地方?

您的问题是这一行:

return [q.get() for _ in xrange(len(job_list))]
若作业列表包含的元素超过50个,那个么您尝试从队列中读取的结果要多于输入的结果。因此:

return [q.get() for _ in xrange(len(job_list[:50]))]
或者,更好的是:

MAX_LEN = 50
...
threads = [... for job in job_list[:MAXLEN]]
...
return [q.get() for _ in job_list[:MAXLEN]]
[编辑]

看起来你希望你的程序做一些不同于它所做的事情。您的程序获取job_列表中的前50个条目,在一个线程中处理每个条目,并忽略所有其他作业。根据您下面的评论,我假设您希望处理所有工作,但一次只处理50个。为此,您应该使用线程池。在Python>=3.2中,可以使用concurrent.futures.ThreadPoolExecutor

在Python<3.2中,您必须自己滚动:

CHUNK_SIZE = 50

def fetch_parallel(job_list):
    results = []
    queue = Queue.Queue()
    while job_list:
        threads = [threading.Thread(target=avhash, args=(job, queue))
                      for job in job_list[:CHUNK_SIZE]]
        job_list = job_list[CHUNK_SIZE:]
        for thread in threads:
            thread.daemon = True
            thread.start()
        for thread in threads:
            thread.join()
        results.extend(queue.get() for _ in threads)
    return results
未经测试


[/EDIT]

您好,代码运行时没有错误,但只返回前50个结果。