迭代数据框的更快方法?

Faster way to iterate over dataframe?

我有一个数据框,其中每一行都是一条记录,我需要在 post 请求的正文中发送每条记录。现在我正在遍历数据框来完成这个。我受到每个记录必须单独 post 的事实的限制。有没有更快的方法来完成这个?

迭代数据框不是这里的问题。问题是您必须等待服务器响应您的每个请求。与 CPU 遍历数据帧所需的时间相比,网络请求需要花费大量时间。换句话说,您的程序是 I/O 绑定的,而不是 CPU 绑定的。

一种加快速度的方法是使用协程。假设您必须发出 1000 个请求。不是触发一个请求,而是等待响应,然后触发下一个请求,依此类推,您一次触发 1000 个请求并告诉 Python 等到您收到所有 1000 个响应。

由于您没有提供任何代码,这里有一个小程序来说明这一点:

import aiohttp
import asyncio
import numpy as np
import time

from typing import List

async def send_single_request(session: aiohttp.ClientSession, url: str):
    async with session.get(url) as response:
        return await response.json()

async def send_all_requests(urls: List[str]):
    async with aiohttp.ClientSession() as session:
        # Make 1 coroutine for each request
        coroutines = [send_single_request(session, url) for url in urls]
        # Wait until all coroutines have finished
        return await asyncio.gather(*coroutines)

# We will make 10 requests to httpbin.org. Each request will take at least d
# seconds. If you were to fire them sequentially, they would have taken at least
# delays.sum() seconds to complete.
np.random.seed(42)
delays = np.random.randint(0, 5, 10)
urls = [f"https://httpbin.org/delay/{d}" for d in delays]

# Instead, we will fire all 10 requests at once, then wait until all 10 have
# finished.
t1 = time.time()
result = asyncio.run(send_all_requests(urls))
t2 = time.time()

print(f"Expected time: {delays.sum()} seconds")
print(f"Actual time: {t2 - t1:.2f} seconds")

输出:

Expected time: 28 seconds
Actual time: 4.57 seconds

您必须阅读一些关于协同程序及其工作原理的内容,但在大多数情况下,它们对于您的用例来说并不太复杂。这有几个警告:

  1. 您的所有请求必须相互独立。
  2. 服务器上的速率限制必须足以处理您的工作量。例如,如果它限制你每分钟 2 个请求,那么除了升级到不同的服务层之外别无他法。