如何并行化 python api 调用?
Posted
技术标签:
【中文标题】如何并行化 python api 调用?【英文标题】:How to parallelize python api calls? 【发布时间】:2018-09-14 17:29:32 【问题描述】:我正在开发一个程序,当我的艺术家在 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
【问题讨论】:
ThreadPoolExecutor
Example from the docs
【参考方案1】:
所以基本上你在这里有 3 个选项。
-
使用线程
多处理
异步代码(如果您使用的是 python 3.5 或更高版本)
线程 将在您的进程中生成多个线程,使其并行运行,但缺点是它会在内存使用中引入大量开销,并且不是最有效的并行方式,因为正在发生上下文切换在处理器级别。 threading_toolbelt 示例:https://toolbelt.readthedocs.io/en/latest/threading.html
Multiprocessing 将产生 Python 引入的多个进程,甚至更多的资源消耗开销,因为它在内存中为每个进程保存了整个 Python 进程堆栈。而且进程之间的通信并不是世界上最琐碎的事情。
Async 如果您使用的是 python3.5 或更高版本,这里绝对是最好的解决方案。您可能会认为它在某种程度上类似于线程,但在事件循环级别进行上下文切换并且没有应对 python 堆栈的内存开销。您需要使用异步请求库才能做到这一点。 (这里有一个:asyncio)。以及用法示例:https://pawelmhm.github.io/asyncio/python/aiohttp/2016/04/22/asyncio-aiohttp.html
总之,从最佳到最差的排序是:
异步 线程 多处理【讨论】:
以上是关于如何并行化 python api 调用?的主要内容,如果未能解决你的问题,请参考以下文章