使用队列和无响应线程进行Python线程处理

时间:2015-10-15 22:12:48

标签: python multithreading queue blocking

在我的python代码中,我调用外部api来获取图像的URL列表。对于每个这些网址,我创建了一个线程来生成缩略图。以下是感兴趣的代码的一部分:

def process_image(image, size, cropping, counter, queue):
    options = dict(crop=cropping)
    img = get_thumbnail(image['url'], size, **options)
    queue.put((counter, img))
    return img

...

queue = Queue()

# Get some information about an artist. Images are also included.
artist = get_profile(artist_id, buckets)

# Generate images' thumbnails
threads = [Thread(target=process_image, args=(img, '500', 'center', counter, queue)) for counter, img in enumerate(artist.data['images'])]

for p in threads:
    p.start()
for p in threads:
    p.join()

imgs = []
# Collect processed images from threads
while not queue.empty():
    el = queue.get()
    imgs.append((el[0], el[1]))

我的问题是有些网址不起作用,我的意思是如果我在浏览器中复制粘贴网址,它会继续加载,加载和加载更多,直到返回超时。显然我添加了多线程来加快速度。导致此问题的第一个URL是第4个,所以如果我添加...

# Generate images' thumbnails
threads = [Thread(target=process_image, args=(img, '500', 'center', counter, queue)) for counter, img in enumerate(artist.data['images'])]
treads = threads[:3]

一切都按预期工作,非常快,否则会长时间被阻止,最终终止执行。我想为线程运行该函数设置某种超时(比如1秒),如果url不起作用,并且线程在超时之前没有完成,那么退出该线程。

提前感谢您的帮助。

3 个答案:

答案 0 :(得分:0)

如果get_thumbnail函数是你的,我会按照@turbulencetoo的建议建立一个超时。否则,请查看signal模块,将超时添加到process_image。正如评论中所建议的那样,您还可以看到使用多处理与线程的进一步优势。多处理模块的接口几乎与线程的接口相同,因此切换工作不会太多。

答案 1 :(得分:0)

other questions中所述,没有官方方法可以杀死Python中的线程。如果线程正在执行您控制的工作(而不是阻止例如网络请求),您可以使用信号变量让线程自行杀死,但这似乎并非如此。

为了并行下载多个资源,您可能希望使用像pycurl这样的库,它将使用特定于操作系统的功能来允许多个请求在单个线程上异步执行。这使您可以使用像set_timeout这样的方法来提供一种相当简洁的方法来处理您描述的问题。

答案 2 :(得分:0)

我终于找到了一个基于@ turbulencetoo评论的解决方案。

get_thumbnail不是我的代码的一部分,而是外部库的,所以我无法在我的代码中设置任何类型的超时。我认为这个库在url请求期间没有配置项来设置超时,但显然有(我已经读过它并且我误解了)。

@RobertB是的,join()有一个超时参数,我已经尝试设置该参数,但它没有用。