ThreadPoolExecutor以迭代方式而非线程运行

时间:2018-08-12 10:10:06

标签: python multithreading

我有以下代码:

def getdata(page, hed, limit):
    data = []
    print page
    datarALL = []
    url = 'http://...WithTotal=true&cultureid=1&offset={0}&limit={1}'.format(value_offset, value_limit)
    print page
    print url
    responsedata = requests.get(url, data=data, headers=hed, verify=False)
    if responsedata.status_code == 200:  # 200 for successful call
        responsedata = responsedata.text
        jsondata = json.loads(responsedata)
        if "results" in jsondata:
            if jsondata["results"]:
                datarALL = datarALL + jsondata["results"]
    print "page {} finished".format(page)
    return data


def start(data, auth_token):
    # # ---  Get data from API --
    hed = {'Authorization': 'Bearer ' + auth_token, 'Accept': 'application/json'}

    urlApi = 'http://...WithTotal=true&cultureid=1&offset=0&limit=1'
    responsedata = requests.get(urlApi, data=data, headers=hed, verify=False)
    num_of_records = int(math.ceil(responsedata.json()['total']))
    value_limit = 249  # Number of records per page.
    num_of_pages = num_of_records / value_limit
    print num_of_records
    print num_of_pages
    pages = [i for i in range(0, num_of_pages - 1)]
    from concurrent.futures import ThreadPoolExecutor, as_completed
    datarALL = []
    with ThreadPoolExecutor(max_workers=num_of_pages) as executor:
        futh = [executor.submit(getdata(page, hed, value_limit), page) for page in pages]
        for data in as_completed(futh):
            datarALL = datarALL + data.result()
    return datarALL

基本上start()创建页面,getdata()每页运行。 印刷品显示给我:

0
http://...WithTotal=true&cultureid=1&&offset=0&limit=249
page 0 finished
1
http:/...WithTotal=true&cultureid=1&&offset=249&limit=249
page 1 finished
etc...

但是,我希望所有页面将在同一时间创建,然后每个线程在线程获得CPU时间时运行,但实际上发生的是仅在getdata()完成时创建下一页。这意味着线程在这里是无用的。我应该注意,每个getdata()通话大约需要4-5分钟才能完成。

我怀疑问题出在这里

futh = [executor.submit(getdata(page, hed, value_limit), page) for page in pages]

它等待getdata()完成之后才能运行下一个循环。

如何修复它并使它与线程一起使用?

2 个答案:

答案 0 :(得分:3)

问题是您根本不在执行程序中执行任务。相反,您要调用5分钟函数,然后尝试将其 result 作为任务执行:

[executor.submit(getdata(page, hed, value_limit), page) for page in pages]

getdata(page, hed, value_limit)是一个函数调用:它调用getdata并等待其返回值。

您需要做的就是将函数本身传递给submit,如下所示:

executor.submit(getdata, page, hed, value_limit)

我不确定您要如何使用多余的, page,但是如果您想要(future, page)元组的列表,那就是:

[(executor.submit(getdata, page, hed, value_limit), page) for page in pages]

答案 1 :(得分:1)

您必须向executor.submit提交一个函数(实际上没有调用它!)。因此,在您的特定情况下,应在hed函数中修复value_limitgetdata参数,以使其具有单个参数page的功能。

最简单的解决方案可能如下所示:

getdata_partial = lambda page: getdata(page, hed, value_limit)

然后您可以按如下所示使用它:

futh = [executor.submit(getdata_partial, page) for page in pages]

另一种可能的解决方案是使用functools.partial。您可能会发现它更加优雅,但想法仍然相同。