将python线程结果合并到一个列表中

时间:2016-04-06 22:14:10

标签: python multithreading http concurrency urllib2

我正在尝试修改此处显示的解决方案:What is the fastest way to send 100,000 HTTP requests in Python?,除了检查标头状态而不是我正在发出返回字典的API请求,我希望所有这些API请求的最终结果都是所有词典的列表。

这是我的代码 - 考虑到api_calls是一个列表,其中包含为json请求打开的每个URL ...

from threading import Thread
from Queue import Queue

concurrent = 200 

def doWork():
    while True:
        url = q.get()
        result = makeRequest(url[0])
        doSomethingWithResult(result, url)
        q.task_done()

def makeRequest(ourl):
    try:
        api_call = urlopen(ourl).read()
        result = json.loads(api_call)
        return result, ourl
    except:
        return "error", ourl

def doSomethingWithResult(result, url):
  print(url,result)

q = Queue(concurrent * 2)
for i in range(concurrent):
    t = Thread(target=doWork)
    t.daemon = True
    t.start()
try:
    for url in api_calls:
        q.put(url)
    q.join()
except KeyboardInterrupt:
    sys.exit(1)

与链接的示例一样,目前这将成功打印每行上的url结果。我想要做的是将(url,result)添加到每个线程的列表中,然后在最后将它们连接到一个主列表中。我无法弄清楚如何拥有这个主列表并在最后加入结果。任何人都可以帮助我在doSomethingWithResult中修改的内容吗?如果我正在做一个大循环,我只会有一个空列表,我会在每个API请求后将结果附加到列表中,但我现在不知道如何模仿这个我正在使用线程。

我希望一个共同的回答是使用https://en.wikipedia.org/wiki/Asynchronous_I/O,如果这是建议,那么我会感谢有人提供了一个例子来完成我上面链接的代码。

1 个答案:

答案 0 :(得分:4)

请改用ThreadPool。它为你做了繁重的工作。这是一个提取几个网址的工作示例。

import multiprocessing.pool
concurrent = 200 

def makeRequest(ourl):
    try:
        api_call = urlopen(ourl).read()
        result = json.loads(api_call)
        return "success", ourl
    except:
        return "error", ourl

def main():
    api_calls = [
        'http:http://jsonplaceholder.typicode.com/posts/{}'.format(i)
        for i in range(1,5)]

    # a thread pool that implements the process pool API.
    pool = multiprocessing.pool.ThreadPool(processes=concurrent)
    return_list = pool.map(makeRequest, api_calls, chunksize=1)
    pool.close()
    for status, data in return_list:
        print(data)

main()