Si recién está comenzando en Python y desea obtener más información, tome el curso de introducción a la ciencia de datos en Python de DataCamp.
Introducción
Threading permite tener diferentes partes de su proceso de ejecutar simultáneamente (Fuente: RealPython). Estas diferentes partes son generalmente individuales y tienen una unidad de ejecución separada que pertenece al mismo proceso., El proceso no es más que un programa en ejecución que tiene unidades individuales que se pueden ejecutar simultáneamente. Por ejemplo, un navegador web podría ser un proceso, una aplicación que ejecuta varias cámaras simultáneamente podría ser un proceso; un videojuego es otro ejemplo de un proceso.
dentro de un proceso viene el concepto de subproceso múltiple o comúnmente conocido como subproceso múltiple, donde varios subprocesos trabajan juntos para lograr un objetivo común. El beneficio más crucial de usar subprocesos es que le permite ejecutar el programa en paralelo.,
entendamos el concepto de enhebrado con la ayuda de un ejemplo. Imagine que tiene una aplicación que cuenta el número de automóviles que entran y salen del estacionamiento del centro comercial. Su aparato tiene varias cámaras que monitorean la entrada y salida que se conectan a un dispositivo central. Cada cámara tendrá un algoritmo para monitorear el flujo de automóviles, que pertenecerán al mismo proceso o programa. Sin embargo, cada cámara, junto con el algoritmo en el que se está ejecutando, podría ser parte de un hilo separado., No solo eso, sino que incluso los fotogramas que se leen desde la cámara y el algoritmo que predice los fotogramas también podrían ser dos hilos separados.
otro ejemplo podría ser un videojuego en el que el proceso tiene que ejecutar las tareas en paralelo como los gráficos, la interacción del usuario y la creación de redes (mientras se juegan juegos multijugador) porque tiene que ser responsive en todo momento. Y para lograr esto, tiene que hacer uso del concepto de multi-threading, donde cada hilo sería responsable de ejecutar cada tarea independiente e individual.,
un hilo tiene su flujo de ejecución, lo que significa que el proceso tendrá varias cosas sucediendo a la vez.
es importante tener en cuenta que cada proceso tiene al menos un hilo, y que se llama el main thread
. Si su programa no tiene ningún subproceso definido, entonces al menos tendrá el subproceso principal, es decir, el proceso en sí.
si nos fijamos en el diagrama anterior, hay un proceso que consiste en el hilo principal que consiste en variables globales y tres hilos diferentes t1, t2 y t3. Cada subproceso tiene sus variables locales y el flujo de ejecución del código., Los hilos generalmente comparten los recursos del proceso, al igual que los recursos disponibles para el hilo principal también se compartirán entre los tres hilos t1, t2 y t3. Todos los hilos tendrán acceso a las variables globales mientras tienen sus propias variables locales.,
Hay diferentes tipos de subprocesos:
- Kernel thread
- User thread
- combinación de kernel y User thread
ahora veamos algunas de las ventajas de tener threading en su programa:
-
Multi-threading permite al programa acelerar la ejecución siempre que tenga múltiples CPU.
-
también le permite realizar otras tareas mientras las operaciones de E / S se realizan con la ayuda de varios subprocesos o incluso el subproceso principal junto con un solo subproceso., Por ejemplo, la velocidad a la que los fotogramas de la cámara son leídos e inferidos por el algoritmo será manejada por diferentes hilos. Por lo tanto, el algoritmo no tendrá que esperar a que se ingrese el marco, y la parte de lectura del marco no tendrá que esperar a que se complete la ejecución del algoritmo para poder leer el siguiente marco.
- Los subprocesos dentro del mismo proceso pueden compartir la memoria y los recursos del subproceso principal.,
desafíos del subproceso:
-
recuerde que Python funciona basado en la implementación de CPython, lo que limita solo un subproceso a ejecutarse a la vez, por lo tanto, el subproceso puede no acelerar todas las tareas. Y la razón esencial detrás de esto es global Interpreter Lock (GIL).
si desea aprender sobre GIL, no dude en Revisar este tutorial.
-
si está buscando acelerar la tarea intensiva de la CPU, entonces el subproceso puede no ser la mejor solución para usted. En tales casos, el procesamiento múltiple se considera útil.,
-
para ejecutar un programa que comprende varios subprocesos, necesita cambiar rápidamente entre subprocesos; por lo tanto, la programación debe hacerse en programas donde tiene muchos subprocesos.
-
compartir recursos también puede ser un problema ya que todos los subprocesos comparten los mismos recursos y memoria de las variables globales. Por lo tanto, las operaciones realizadas en un subproceso podrían causar un error de memoria para otro subproceso, o el otro subproceso podría no conseguir que la memoria realice su tarea.,
Threading en Python
-
en Python, el módulo threading es un Módulo incorporado que se conoce como
threading
y se puede importar directamente. -
dado que casi todo en Python se representa como un objeto, threading también es un objeto en Python. Un hilo es capaz de
- contener datos,
- almacenados en estructuras de datos como diccionarios, listas, conjuntos, etc.
- Se puede pasar como parámetro a una función.
-
Un hilo también puede ser ejecutado como un proceso.,
-
un hilo en Python puede tener varios estados como:
- Wait,
- Locked.
ahora Vamos a aprender cómo se puede implementar roscado en Python.
módulo Thread en Python3
tenga en cuenta que Python3 es compatible con versiones anteriores con el módulo thread
, que existe en Python2.7. En Python3, se puede importar como módulo _thread
. Por lo tanto, tomemos un ejemplo y entendamos el módulo _thread
.,
import _thread #thread module importedimport time #time module
vamos a definir una función llamada thread_delay
, que tomará dos parámetros como entrada, es decir, el nombre del hilo y el retraso. Dentro de esta función, usted:
- Definir un contador con cero,
- Entonces usted va a hacer un bucle con un bucle while que se ejecutará por tres veces,
- dentro del bucle while, usted pondrá
time.sleep()
para añadir retraso, este retraso será útil para entender la ejecución del hilo., Este retardo será en segundos, - Luego incrementará su contador en 1,
- para ver si la ejecución de su subproceso va sin problemas, imprimirá el nombre del subproceso y la hora en la que se ejecuta el subproceso.
def thread_delay(thread_name, delay): count = 0 while count < 3: time.sleep(delay) count += 1 print(thread_name, '-------->', time.time())
ahora para agregar la funcionalidad del subproceso en la función anterior o para ejecutar la función anterior en el subproceso, usaría el método start_new_thread
, que está dentro del _thread module
.
veamos el docstring del método start_new_thread
.,
?_thread.start_new_thread
Vamos a pasar en la función thread_delay
sin paréntesis y los dos argumentos, es decir, nombre del hilo y el tiempo de retraso (para visualizar la ejecución del hilo, ya que es muy rápido).
_thread.start_new_thread(thread_delay, ('t1', 1))_thread.start_new_thread(thread_delay, ('t2', 3))
de la salida anterior, puede ver que el subproceso t1
comienza a ejecutarse primero., Mientras tanto, thread t2
espera ya que hay un retardo de 3 segundos, y tan pronto como ese retardo finaliza, threadt2
se ejecuta, y también, el retardo para threadt1
es de solo 1 segundo.
ahora Vamos a cambiar el retraso de t2
a 5 segundos, que daría inicio t2
después de t1
se han terminado de ejecutar desde t1
tendrá sólo 3 segundos para completar su ejecución.,
_thread.start_new_thread(thread_delay, ('t1', 1))_thread.start_new_thread(thread_delay, ('t2', 5))
implementando threading usando el módulo Threading
usemos el mismo ejemplo que usaste anteriormente, pero esta vez usarás el módulo threading
en lugar del módulo _thread
.
import threadingimport time
def thread_delay(thread_name, delay): count = 0 while count < 3: time.sleep(delay) count += 1 print(thread_name, '-------->', time.time())
Dentro de la etiqueta threading
módulo es un Thread
clase, que es un espíritu similar a la de start_new_thread
función de la etiqueta _thread
módulo.,
veamos el docstring de Thread
class, que toma varios parámetros como group, target (como una función), args, etc.
?threading.Thread
En el Hilo constructor de la clase, usted pasará a la función de destino thread_delay
y los argumentos de la función.,
t1 = threading.Thread(target=thread_delay, args=('t1', 1))t2 = threading.Thread(target=thread_delay, args=('t2', 3))
en el módulo threading, para ejecutar o ejecutar el hilo, se hace uso del método start()
, que simplemente se encarga de ejecutar el hilo.
?t1.start
t1.start()t2.start()
también se utiliza la etiqueta join
método, lo que significa que espere hasta que todo el hilo de ejecución es completa., Así que cualquier código que haya escrito después del método join
solo se ejecutará una vez que estos subprocesos hayan terminado.
?t1.join
t1.start()t2.start()t1.join()t2.join()print("Thread execution is complete!")
Ahora vamos a calcular el volumen del cubo y el cuadrado con el hilo concepto, que es bastante sencillo.
def volume_cube(a): print ("Volume of Cube:", a*a*a)
def volume_square(a): print ("Volume of Square:", a*a)
t1 = threading.Thread(target=volume_cube, args=(2))t2 = threading.Thread(target=volume_square, args=(3))
t1.start()t2.start()t1.join()t2.join()print("Thread execution is complete!")
Espere; ¿qué? Tan pronto como ejecutó el método de inicio, resultó en un error., Esto se debe a que el parámetro args
espera una tupla, y dado que el parámetro volume_cube
y volume_square
solo espera un parámetro, por lo tanto, debe poner una coma en el parámetro args
después de especificar argumento de las funciones.
t1 = threading.Thread(target=volume_cube, args=(2,))t2 = threading.Thread(target=volume_square, args=(3,))
t1.start()t2.start()t1.join()t2.join()print("Thread execution is complete!")
Volume of Cube: 8Volume of Square: 9Thread execution is complete!
ahora Vamos a aprender a utilizar el roscado como una subclase.,
Enhebrado como subclase
en esta sección, aprenderá a crear subclase de la clase thread, que está disponible dentro del módulo threading, y luego crear instancias de subproceso t1
y t2
fuera de esa clase.
usarías la misma funciónthread_delay
aquí también.
Ahora vamos a entender el código anterior paso a paso:
-
ha definido una clase como
DataCampThread
, y en el argumento class, ha pasado la clasethreading.Thread
., La razón por la que lo hace es que desea crear una subclase desde el módulo threading. Hacer esto le permite usar todos los métodos que están disponibles en la clasethreading.Thread
similar al concepto de herencia. -
a continuación, definió el método init de la clase DataCampThread y pasó la función junto con el retraso. El init es un constructor similar a los parámetros que pasó a la clase
threading.Thread
, aquí estaría pasando a la claseDataCampThread
., -
luego inicializa el método init del subproceso principal.Thread class y luego igualar nombre y delay.
-
A continuación, define el método
run
, recuerde que aquí definió el métodostart
, que básicamente debajo del capó llama al métodorun
. Dado que ha heredado la clase main, se le permite realizar cambios en el métodorun
., Por lo tanto, cuando llame al métodostart
, cualquier modificación que realice en el métodorun
se reflejará ahora.
Conclusión
¡Felicitaciones por terminar el tutorial.
este tutorial fue una introducción básica al threading en python. Sin embargo, el hilo es un tema muy vasto y vital, y algunos conceptos podrían haber quedado inexplorados. Siéntase libre de mirar más métodos de roscado como Conteo activo, hilo actual, etc.
si desea obtener más información, también consulte el paralelismo basado en subprocesos de Python.,
si recién está comenzando en Python y le gustaría aprender más, tome el curso de introducción a la ciencia de datos en Python de DataCamp.