threads thread parallel lock example python http parallel-processing download feed

python - thread - Biblioteca o herramienta para descargar múltiples archivos en paralelo



python pool thread (10)

Estoy buscando una biblioteca de Python o una herramienta de línea de comandos para descargar varios archivos en paralelo. Mi solución actual es descargar los archivos secuencialmente, lo cual es lento. Sé que puedes escribir fácilmente una solución de subprocesos a medias en python, pero siempre tengo problemas molestos cuando uso subprocesos. Es para encuestar una gran cantidad de feeds xml de sitios web.

Mis requerimientos para la solución son:

  1. Debe ser interrumpible. Ctrl + C debe terminar inmediatamente todas las descargas.
  2. No debe haber procesos sobrantes que deba eliminar manualmente utilizando kill, incluso si el programa principal se bloquea o si se produce una excepción.
  3. Debería funcionar en Linux y Windows también.
  4. Debe volver a intentar las descargas, ser resistente a los errores de la red y debe expirar correctamente.
  5. Debería ser inteligente acerca de no atacar al mismo servidor con más de 100 descargas simultáneas, sino ponerlas en una cola de forma sana.
  6. Debe manejar códigos de estado http importantes como 301, 302 y 304. Eso significa que para cada archivo, debe tomar el último valor modificado como entrada y solo descargarlo si ha cambiado desde la última vez.
  7. Preferiblemente debería tener una barra de progreso o debería ser fácil escribir una barra de progreso para que monitoree el progreso de la descarga de todos los archivos.
  8. Preferiblemente, debería aprovechar las ventajas del mantenimiento de http para maximizar la velocidad de transferencia.

Por favor , no sugiera cómo puedo implementar los requisitos anteriores. Estoy buscando una solución ya preparada, probada en la batalla.

Supongo que también debo describir para qué lo quiero ... Tengo aproximadamente 300 fuentes de datos diferentes como archivos con formato xml de 50 proveedores de datos. Cada archivo tiene un tamaño de entre 100kb y 5mb. Necesito encuestarlos con frecuencia (como una vez cada pocos minutos) para determinar si alguno de ellos tiene datos nuevos que debo procesar. Por lo tanto, es importante que el descargador utilice el almacenamiento en caché de http para minimizar la cantidad de datos para obtener. También usa compresión gzip obviamente.

Entonces el gran problema es cómo usar el ancho de banda de la manera más eficiente posible sin sobrepasar ningún límite. Por ejemplo, un proveedor de datos puede considerar que es un abuso si abres 20 conexiones simultáneas a sus fuentes de datos. En su lugar, puede ser mejor usar una o dos conexiones que se reutilizan para varios archivos. O su propia conexión puede estar limitada de formas extrañas. Mi isp limita la cantidad de búsquedas de DNS que puede hacer, por lo que algún tipo de almacenamiento en caché de DNS sería bueno.



El subprocesamiento no es "a medias" a menos que seas un mal programador. El mejor enfoque general para este problema es el modelo productor / consumidor. Tiene un productor de URL dedicado y N subprocesos de descarga dedicados (o incluso procesos si utiliza el modelo de multiprocesamiento).

En cuanto a todos sus requisitos, TODOS PUEDEN hacerse con el modelo normal de hilos de Python (sí, incluso capturar Ctrl + C: lo he hecho).



Hay muchas opciones, pero será difícil encontrar una que se ajuste a todas sus necesidades.

En tu caso, prueba este enfoque:

  1. Crear una cola.
  2. Coloque las URL para descargar en esta cola (u "objetos de configuración" que contienen la URL y otros datos como el nombre de usuario, el archivo de destino, etc.).
  3. Crea un conjunto de hilos.
  4. Cada subproceso debe intentar obtener una URL (o un objeto de configuración) de la cola y procesarla.

Utilice otro hilo para recopilar los resultados (es decir, otra cola). Cuando el número de objetos de resultado == número de coloca en la primera cola, se termina.

Asegúrese de que toda la comunicación se realiza a través de la cola o el "objeto de configuración". Evite acceder a estructuras de datos que se comparten entre subprocesos. Esto debería ahorrarle el 99% de los problemas.


Hoy en día hay excelentes librerías de Python que tal vez quieras usar - urllib3 y requests


Intente utilizar aria2 través del módulo de subprocess python simple. Proporciona todos los requisitos de su lista, excepto 7, listo para usar, y 7 es fácil de escribir. aria2c tiene una bonita interfaz xml-rpc o json-rpc para interactuar con ella desde tus scripts.



Puedes probar pycurl, aunque la interfaz no es fácil al principio, pero una vez que miras los ejemplos, no es difícil de entender. Lo he usado para buscar miles de páginas web en paralelo en una caja de Linux pobre.

  1. No tienes que lidiar con hilos, por lo que termina con gracia y no hay procesos que queden atrás.
  2. Ofrece opciones para el tiempo de espera y el manejo del estado de http.
  3. Funciona tanto en linux como en windows.

El único problema es que proporciona una infraestructura básica (básicamente, solo una capa de python sobre la excelente biblioteca de rizos). Tendrá que escribir algunas líneas para lograr las características que desee.


Yo sugeriría Twisted, aunque no es una solución lista para usar, pero proporciona los bloques de construcción principales para obtener cada característica que se enumera de una manera fácil y no utiliza subprocesos.

Si está interesado, eche un vistazo a los siguientes enlaces:

Según sus requisitos:

  1. Apoyado fuera de la caja
  2. Apoyado fuera de la caja
  3. Apoyado fuera de la caja
  4. Tiempo de espera admitido de inmediato, otro manejo de errores se realiza a través de diferidos
  5. Se logra fácilmente usando cooperadores (ejemplo 7)
  6. Apoyado fuera de la caja
  7. No soportadas, existen soluciones (y no son tan difíciles de implementar)
  8. No soportado, se puede implementar (pero será relativamente difícil)

Utilicé las urllib.urlretrieve estándar para eso, urllib.urlretrieve para ser preciso. Podcasts descargados de esta manera, a través de un simple grupo de subprocesos, cada uno utilizando su propia recuperación. Hice unas 10 conexiones simultáneas, más no debería ser un problema. Continuar una descarga interrumpida, tal vez no. Ctrl-C podría ser manejado, supongo. Trabajó en Windows, instaló un controlador para las barras de progreso. En total, 2 pantallas de código, 2 pantallas para generar las URL para recuperar.