python - 如何并行化 python api 调用?

标签 python parallel-processing python-requests spotify

我正在开发一个程序,当我的艺术家在 Spotify 上发布新音乐时,它会通过电子邮件向我发送电子邮件。它通过在脚本运行时获取每个艺术家拥有的专辑数量并将结果与​​保存为 CSV 文件的前一天进行比较来实现此目的。

这涉及 API 调用来验证艺术家是否在 Spotify 上(我收到错误消息,某些专辑不在 Spotify 上),然后获取该艺术家的专辑数量。这些电话非常耗时,尤其是当我有近千名个人艺术家时。

我想知道如何并行化这些 API 调用或任何其他建议来加速整个程序。下面链接的是包含 API 调用的代码部分。感谢您提前抽出时间。

# given artist name returns all info related to artist 
def get_artist_info(spotipy_instance, name):
    results = spotipy_instance.search(q='artist:' + name, type='artist')
    items = results['artists']['items']
    if len(items) > 0:
        return items[0]
    else:
        return None

# returns list of all albums given artist name 
def get_artist_albums(spotipy_instance, artist):
    albums = []
    results = spotipy_instance.artist_albums(artist['id'], album_type='album')
    albums.extend(results['items'])
    while results['next']:
        results = spotipy_instance.next(results)
        albums.extend(results['items'])
    seen = set() # to avoid dups
    for album in albums:
        name = album['name']
        # print(album['name'] + ": " + album['id'])
        if name not in seen:
            seen.add(name.encode('utf-8'))
    return list(seen)

def get_all_artists_info(spotipy_instance, list_of_all_artists):
    all_artist_info = []
    print("Getting number of albums for all artists")
    # bar = Bar('Loading...', max=len(list_of_all_artists), suffix='%(index)d/%(max)d - %(percent).1f%% - %(eta)ds')
    for artist_name in list_of_all_artists:
        # increment_progress_bar(bar)
        # print(artist_name)
        artist_info = get_artist_info(spotipy_instance, artist_name)
        if artist_info is not None:  
            albums = get_artist_albums(spotipy_instance, artist_info)
            # print(albums)
            artist = Artist(artist_name, len(albums), albums)
            all_artist_info.append(artist)
        else:
            print("\nCan't find " + artist_name)
            artist = Artist(artist_name, -1, [])
            all_artist_info.append(artist)
        # print(" ")
    # bar.finish()
    print("Done!\n")

    all_artist_info.sort(key=lambda artist: artist.name)

    return all_artist_info

最佳答案

所以基本上你有 3 个选择。

  1. 使用线程
  2. 多处理
  3. 异步代码(如果您使用的是 python 3.5 或更高版本)

线程将在您的进程中生成多个线程,使其并行运行,但缺点是它会在内存使用方面带来很大的开销,并且不是最有效的并行方式,因为正在发生上下文切换在处理器级别。 threading_toolbelt 示例:https://toolbelt.readthedocs.io/en/latest/threading.html

多处理将产生多个Python进程,引入更多的资源消耗开销,因为它在内存中为每个进程保存了整个Python进程堆栈。而且进程之间的通信并不是世界上最琐碎的事情。

如果您使用的是 python3.5 或更高版本,

Async 绝对是最好的解决方案。您可能会认为它在某种程度上类似于线程,但在事件循环级别上进行上下文切换,并且没有处理 python 堆栈的内存开销。您需要使用异步请求库才能做到这一点。 (这里是一个: asyncio )。用法示例:https://pawelmhm.github.io/asyncio/python/aiohttp/2016/04/22/asyncio-aiohttp.html

总而言之,从最好的选择到最差的选择是:

  • 异步
  • 线程化
  • 多处理

关于python - 如何并行化 python api 调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49663091/

相关文章:

python - 使用Python获取https网站时超时

python - 使用请求模块打开的文件太多

python - 如何在另一个 python 文件中运行我的 python 文件?

python - openCV3:在opencv中对图像进行形态转换时未获得预期的输出

cuda - CUDA 的 __syncthreads() 和 blockIdx.x 的 OpenCL 模拟是什么?

bash - 有没有办法并行化 bash for 循环?

c# - 并行线程中的多个 dbcontext,EntityException "Rerun your statement when there are fewer active users"

python - 统一打印某个数的倍数

python - 使用Azure AD对React应用程序和后端应用程序进行身份验证(python)

Python - 正则表达式西里尔字母与拉丁字母混合