当前位置: 首页 > 科技观察

如何使用Python异步编程进行API调用

时间:2023-03-18 13:20:58 科技观察

如何使用Python异步编程调用API本文转载请联系区块链研究院公众号。在本文中,我将向您展示如何使用Python进行异步编程,以便您可以更快地进行更多API调用。让我们开始吧。请求库通常,当Python使用者希望进行API调用时,他们会查找请求库。语法是我最喜欢的,因为如果我想进行API调用,我可以运行:importrequestsresponse=requests.get("http://example.com/")print(response)(10):response=requests.get("http://example.com/")print(response)每次我对example.com进行API调用时,我必须做:向example.com发送请求。等待回应。得到回应。如果您尝试获取大量数据(例如,如果我想从AlphaVantageAPI中提取金融科技数据),您将需要一个免费密钥,您可以在此处设置api_key=your_key_here。importrequestsimportosapi_key=os.getenv('ALPHAVANTAGE_API_KEY')url='https://www.alphavantage.co/query?function=OVERVIEW&symbol={}&apikey={}'symbols=['AAPL','GOOG','TSLA','MSFT','PEP']results=[]forsymbolinsymbols:response=requests.get(url.format(symbol,api_key))results.append(response.json())必须等待大约1.5秒才能继续51API调用,那么50次API调用需要11秒,135次API调用需要50秒……如果你想得到2000家公司或者1600万种颜色的数据,我们需要做一些缩放。异步代码与同步代码当我们运行Python代码时,我们的进程会逐行读取代码。当一行正在执行时,没有其他代码可以运行。这就是所谓的同步代码——一切都按顺序进行。在异步代码中,我们可以在另一个任务完成之前继续执行一个任务。例如,如果我们考虑同步烹饪汉堡和蔬菜晚餐,我们的“代码”将如下所示:cook_burger()cook_vegetables()在这种情况下,由于汉堡是同步的,我们在开始之前等待汉堡完成蔬菜。但我们并不总是想等到汉堡做好了才开始烹调蔬菜。所以我们可以同时做饭。一旦完成,我们就可以停止对完成的蔬菜或汉堡做任何事情。在异步代码中,它看起来像这样:结束。我们在事件循环中运行它们以跟踪完成后如何处理它们。您可以通过不断检查其中一个进程是否完成来考虑事件循环。现在你可能听说过多线程,它们是不同的,多线程用于有多个工作线程,而异步只有一个工作线程。事件循环返回到我们的AlphaVantageAPI调用示例。现在,在我们的代码中:发出第一个请求。等待。获得第一反应。提出第二个请求。等待。获得第二个回复。如果我们有五个符号,我们将“等待”五次。那么我们需要改为执行此操作,启动API调用,然后启动其他API调用,最后处理响应。此外,除了执行上述操作,我们还可以:发出第一个请求。提出第二个请求。等待。获得第一反应。获得第二个回复。在第二个例子中,我们只有等待时间!当返回响应时(这可能发生在我们发出请求时),因此我们需要某种方式来处理返回的响应,这称为事件循环。事件循环会定期检查我们的异步操作是否已返回,并安排相应的处理时间。当我们正常运行Python时,并没有运行事件循环来处理这个事件,所以我们需要设置事件循环,以便响应可以按顺序处理。然后,我们可以异步运行我们的代码。进入asyncio和aiohttp我们现在知道,当我们异步运行代码时,我们不必等待代码运行完成,我们可以使用asyncio和aiohttp来完成。importasyncioimportaiohttpimportosimporttimeapi_key=os.getenv('ALPHAVANTAGE_API_KEY')url='https://www.alphavantage.co/query?function=OVERVIEW&symbol={}&apikey={}'symbols=['AAPL','GOOG','TSLA','MSFT','PEP']results=[]asyncdefget_symbols():asyncwithaiohttp.ClientSession()assession:forsymbolinsymbols:response=awaitsession.get(url.format(symbol,api_key),ssl=False)asyncio.run(get_symbols())分解我们将使用asyncio.run(get_symbols()),这将导致事件循环开始并允许我们使用异步代码。此时您会注意到,在前面的许多示例中,它们如何启动事件循环更加明确:loop=asyncio.get_event_loop()results=loop.run_until_complete(get_symbols())loop.close()这段代码块与asyncio.run(get_symbols())完全相同,这是我们的入口点。然后我们转到函数:asyncdefget_symbols():asyncwithaiohttp.ClientSession()assession:forsymbolinsymbols:response=awaitsession.get(url.format(symbol,api_key),ssl=False)我们必须从async关键字开始,它让Python知道这个函数会是异步的,我们可以使用事件循环。我们将使用aiohttp开始一个会话,它是请求的异步版本。我们同样操作,调用aiohttp版本的request.get(即session.get),这里需要添加内容ssl=False。由于session.get是一个异步函数(也称为协程),我们必须等待响应,否则它们将返回到协程本身。现在我们已经请求将代码复制为异步语法,我们仍然需要等待。收集任务我们即将开始所有API调用。importasyncioimportaiohttpimportosimporttimeapi_key=os.getenv('ALPHAVANTAGE_API_KEY')url='https://www.alphavantage.co/query?function=OVERVIEW&symbol={}&apikey={}'symbols=['AAPL','GOOG','TSLA','MSFT','PEP']results=[]defget_tasks(session):tasks=[]forsymbolinsymbols:tasks.append(session.get(url.format(symbol,api_key),ssl=False))returntasksasyncdefget_symbols():asyncwithaiohttp.ClientSession()assession:tasks=get_tasks(session)responses=awaitasyncio.gather(*tasks)asyncio.run(get_symbols())我们有一个名为get_tasks的全新函数。此函数将所有协程组合到一个列表中,因此我们可以立即启动它们。请记住,此列表中的所有函数都必须是已放在事件队列中的异步函数或任务。我们还可以通过以下方式获取所有任务:tasks=[session.get(URL.format(symbol,API_KEY),ssl=False)forsymbolinsymbols]在获取要启动的功能/任务列表后,我们可以使用以下命令get_symbols启动它们函数中的所有内容:responses=awaitasyncio.gather(*tasks)我们将等待所有任务完成并将它们放入响应对象中。responses=awaitasyncio.gather(session.get(URL.format('IBM',API_KEY),ssl=False),session.get(URL.format('AAPL',API_KEY),ssl=False),session.get(URL.format('MSFT',API_KEY),ssl=False))因为*tasks只是一种将列表取消引用为变量的方法。我们“收集”所有任务并将它们发送出去,当它们响应时,事件循环会拾取它们并将它们放入队列中,以便在我们发送完所有任务后进行处理。协程vs.任务在上面的示例中,我们向asyncio.gather函数传递了一个异步协程列表,以便可以将它们调度到事件循环中,这实际上更快地将它们调度到事件循环中!在我们的get_tasks函数中,我们调用了:tasks.append(session.get(url.format(symbol,api_key),ssl=False))我们将session.get函数添加到任务列表中,只在调用Added时添加到事件循环收集。实际上,您可以使用asyncio.create_task将其更快地添加到事件循环中:添加到事件循环中,asyncio.gather函数将等待该任务完成。记住它们的不同之处。协程是函数,而任务是在事件循环中安排的任务。asyncio.gather将等待任务返回和/或将协程安排到事件循环中并等待它们返回。