usando múltiples hilos en Python

Estoy tratando de resolver un problema, donde tengo muchas URL (del orden de diez mil) y necesito descargar el contenido de todas ellas. He estado haciendo esto en un bucle “para enlaces en enlaces:” hasta ahora, pero la cantidad de tiempo que está tomando ahora es demasiado larga. Creo que es hora de implementar un enfoque multiproceso o multiproceso. Mi pregunta es, ¿cuál es el mejor enfoque a seguir?

Sé sobre el locking global de intérpretes, pero como mi problema está vinculado a la red, no a la CPU, no creo que sea un problema. Necesito pasar datos de cada hilo / proceso al hilo / proceso principal. No necesito ayuda para implementar el enfoque ( termine varios subprocesos cuando un hilo complete una tarea que cubra eso), necesito consejos sobre qué enfoque tomar. Mi enfoque actual:

data_list = get_data(...) output = [] for datum in data: output.append(get_URL_data(datum)) return output 

No hay otro estado compartido.

Creo que el mejor enfoque sería tener una cola con todos los datos en ella, y hacer que varios subprocesos de trabajo salgan de la cola de entrada, obtengan los datos de la URL y luego ingresen a la cola de salida.

Estoy en lo cierto? ¿Hay algo que me falta? Esta es la primera vez que implemento código multiproceso en cualquier idioma, y ​​sé que generalmente es un problema difícil.

Para su tarea específica, recomendaría un grupo de trabajadores de multiprocesamiento . Simplemente define un grupo y le dice cuántos procesos desea usar (uno por núcleo del procesador de manera predeterminada), así como una función que desea ejecutar en cada unidad de trabajo. Luego, prepara cada unidad de trabajo (en su caso, esto sería una lista de URL) en una lista y se la da al grupo de trabajadores.

Su salida será una lista de los valores de retorno de su función de trabajador para cada elemento de trabajo en su matriz original. Toda la bondad de multiprocesamiento fresca ocurrirá en el fondo. Por supuesto, también hay otras formas de trabajar con el grupo de trabajadores, pero esta es mi favorita.

Feliz multiprocesamiento!

El método más rápido y eficiente para realizar tareas enlazadas de E / S como esta es un bucle de eventos asíncronos. El libcurl puede hacer esto, y hay un envoltorio de Python para eso llamado pycurl. Usando su interfaz “múltiple” puede hacer actividades de alto rendimiento para el cliente. He hecho más de 1000 capturas simultáneas tan rápido como una.

Sin embargo, la API es bastante baja y difícil de usar. Aquí hay un envoltorio de simplificación, que puede usar como ejemplo.

El mejor enfoque que se me ocurra en su caso de uso será usar un grupo de subprocesos y mantener una cola de trabajo. Los subprocesos en el grupo de subprocesos obtienen trabajo de la cola de trabajo, hacen el trabajo y luego obtienen más trabajo. De esta manera, puede controlar con precisión el número de subprocesos que trabajan en sus URL.

Entonces, cree un WorkQueue, que en su caso es básicamente una lista que contiene las URL que deben descargarse.

Cree un grupo de subprocesos, que cree el número de subprocesos que especifique, las recuperaciones funcionarán desde WorkQueue y lo asignarán a un subproceso. Cada vez que un hilo finaliza y regresa, verifica si las colas de trabajo tienen más trabajo y, en consecuencia, asigna trabajo a ese hilo nuevamente. También puede querer poner un gancho para que cada vez que el trabajo se agregue a la cola de trabajo, sus hilos lo asignen a un hilo libre si está disponible.