在python中同时调用api

Mar*_*ark 2 python api concurrency threadpool gevent

我需要和api交谈才能获得有关团队的信息.每个团队都有一个独特的身份.我用那个id叫api,然后我得到每个团队的队员名单(dicts列表).玩家的关键之一是我可以用来获取有关该玩家的更多信息的另一个ID.我可以捆绑所有这些player_id并打电话给api,以便在一次api通话中获得每个玩家的所有附加信息.

我的问题是:我希望团队数量增长,这可能会非常大.此外,每支球队的球员数量也可能增长.

将这些api调用同时发送到api的最佳方法是什么?我可以使用multiprocessing.dummy中的ThreadPool,我也看过genvent用于这样的事情.

对api的调用需要一些时间来获得返回值(每次批量api调用1-2秒).

现在,我做的是这样的:

for each team:
    get the list of players
    store the player_ids in a list
    get the player information for all the players (passing the list of player_ids)
assemble and process the information
Run Code Online (Sandbox Code Playgroud)

如果我使用ThreadPool,我可以执行以下操作:

create a ThreadPool of size x
result = pool.map(function_to_get_team_info, list of teams)
pool.close()
pool.join()
#process results

def function_to_get_team_info(team_id):
    players = api.call(team_id)
    player_info = get_players_information(players)
    return player_info

def get_players_information(players):
    player_ids = []
    for player in players:
        player_ids.append(player['id'])
    return get_all_player_stats(player_ids)

def get_all_player_stats(players_id):
    return api.call(players_id)
Run Code Online (Sandbox Code Playgroud)

这会同时处理每个团队,并在ThreadPool结果中汇总所有信息.

为了使这个完全并发,我想我需要使我的ThreadPool成为团队数量的大小.但我认为这不会很好.所以,我想知道我是否使用gevent处理这些信息,如果这是一个更好的方法.

任何建议都会非常受欢迎

Mac*_*ach 6

一种解决方案是:

  • 准备要执行的任务列表,在您的案例中,要处理的团队ID列表,
  • 创建N个线程工作者的固定池,
  • 每个工作线程从列表中弹出一个任务并处理任务(下载团队数据),完成后弹出另一个任务,
  • 当任务列表为空时,工作线程停止.

当特定团队的处理需要100个时间单位,其他团队以1个时间单位(平均)处理时,此解决方案可以保护您免受这种情况的影响.

您可以根据团队数量,平均团队处理时间,CPU核心数等来调整线程工作者的数量.

扩展答案

这可以通过Python实现multiprocessing.Pool:

from multiprocessing import Pool

def api_call(id):
    pass # call API for given id

if __name__ == '__main__':
    p = Pool(5)
    p.map(api_call, [1, 2, 3])
Run Code Online (Sandbox Code Playgroud)