Agrega una columna durante la obtención de datos con ThreadPoolExecutor en Python.
Quiero leer diferentes páginas desde el siguiente enlace con números diferentes utilizando ThreadPoolExecutor y guardar los números relacionados en un marco de datos como una nueva columna.
https://booking.snav.it/api/v1/rates/1030/2019-02-25/1042/2019-02-25?lang=1
Los números cambian de la siguiente manera:
from concurrent.futures import ThreadPoolExecutor, as_completed
from pandas import json_normalize
import pandas as pd
import requests
def download_file(url):
url_info = requests.get(url, stream=True)
jdata = url_info.json()
return jdata
nums = [1030, 1031, 1040, 1050, 1020, 1021, 1010, 1023]
urls = [f"https://booking.snav.it/api/v1/rates/{i}/2019-02-25/1042/2019-02-25?lang=1" for i in nums]
with ThreadPoolExecutor(max_workers=14) as executor:
for url in urls:
sleep(0.1)
processes.append(executor.submit(download_file, url))
for index, task in enumerate(as_completed(processes)):
jdata = task.result()
tmp = json_normalize(jdata)
tmp["num"] = nums[index]
df = df.append(tmp)
print(df.head())
En el código anterior, he intentado leer los datos utilizando multi-threading y el número relacionado con cada respuesta json como una nueva columna del marco de datos df
. Pero este código no funciona debido al uso de multi-threading, el orden de los números en nums
no es el mismo que las respuestas json obtenidas. ¿Qué debo hacer?
davy.ai
Para resolver el problema, se puede utilizar un diccionario para mapear las URL con su número correspondiente. Luego, el diccionario se puede pasar como argumento a la función
download_file
, que guardará el número como una columna adicional en el dataframe.Aquí está el código modificado:
En el código modificado, la función
download_file
toma un argumento adicionalnum_map
, que es un diccionario que asigna cada URL a su número correspondiente. La función luego extrae el número del diccionario y lo guarda como una columna adicional en la respuesta json.El diccionario
url_map
se crea utilizando la funciónzip
, que combina las listasurls
ynums
en pares, y la funcióndict
, que crea un diccionario a partir de los pares.En el bucle que envía las tareas al ThreadPoolExecutor, se llama a la función
download_file
con dos argumentos: la URL y el diccionarionum_map
.En el bucle que procesa las tareas completadas, el dataframe
tmp
se agrega al dataframedf
. La variableindex
no es necesaria, ya que el orden de las respuestas en la listaprocesses
corresponde al orden de las URLs en la listaurls
.La salida debería ser un dataframe con los datos json de cada URL y una nueva columna
num
que contiene el número correspondiente.