Увеличьте скорость кода, который выполняет множество вызовов api и хранит все данные в одном фрейме данных

#python #pandas #dataframe #api

Вопрос:

Я написал код, который принимает идентификационный номер и делает запрос к определенному API и возвращает данные, относящиеся к этому идентификационному номеру. Код проходит через фрейм данных и принимает идентификационные номера (примерно 600), возвращает информацию и преобразуется в фрейм данных pandas. Наконец, все фреймы данных объединяются в один фрейм данных. Код работает очень медленно. Есть ли какие-нибудь способы сделать это быстрее? Я не уверен в python и буду признателен, если вы поделитесь кодом решения. Код:

 file = dataframe

list_df = []

for index,row in file.iterrows():

    url = "https://some_api/?eni_number=" str(row['id']) "amp;apikey=some_apikey"

    payload={}
    headers = {
      'Accept': 'application/json'
    }

    response = requests.request("GET", url, headers=headers, data=payload)

    a = json.loads(response.text)

    df_index = json_normalize(a, 'vessels')
    df_index['eni_number'] = row['id']

    list_df.append(df_index)

    #print(df_index)

total = pd.concat(list_df)
 

Ответ №1:

Похоже, узким местом здесь является то, что HTTP-запросы выполняются синхронно, один за другим. Таким образом, большая часть времени тратится впустую на ожидание ответов от сервера.

Возможно, вы получите лучшие результаты, используя асинхронный подход, например, используя grequest для параллельного выполнения всех HTTP-запросов:

 import grequests

ids = dataframe["id"].to_list()
urls = [f"https://some_api/?eni_number={id}amp;apikey=some_apikey" for id in ids]

payload = {}
headers = {'Accept': 'application/json'}
requests = (grequests.get(url, headers=headers, data=payload) for url in urls)

responses = grequests.map(requests)  # execute all requests in parallel

list_df = []
for id, response in zip(ids, responses):
    a = json.loads(response.text)
    df_index = json_normalize(a, 'vessels')
    df_index['eni_number'] = id

    list_df.append(df_index)

total = pd.concat(list_df)
 

Комментарии:

1. У меня эта ошибка:ядро, похоже, умерло. Он автоматически перезапустится.

2. Эта ошибка, похоже, связана с записными книжками Jupyter, можете ли вы попробовать использовать обычный скрипт на python ?

3. Я запустил код на экземпляре aws ec2, и он был таким же