Programación simultánea | Max S | Skillshare

Velocidad de reproducción


1.0x


  • 0.5x
  • 0.75x
  • 1x (Normal)
  • 1.25x
  • 1.5x
  • 1.75x
  • 2x

Programación simultánea

teacher avatar Max S, Power through programming

Ve esta clase y miles más

Obtenga acceso ilimitado a todas las clases
Clases enseñadas por líderes de la industria y profesionales activos
Los temas incluyen ilustración, diseño, fotografía y más

Ve esta clase y miles más

Obtenga acceso ilimitado a todas las clases
Clases enseñadas por líderes de la industria y profesionales activos
Los temas incluyen ilustración, diseño, fotografía y más

Lecciones en esta clase

    • 1.

      Introducción de programación simultánea

      0:46

    • 2.

      Rosca, multiprocesamiento, introducción sincronizada

      13:52

    • 3.

      Rosca en Python

      18:52

    • 4.

      Cómo crear una clase de roscado

      14:58

    • 5.

      Creado un lector de Wikipedia

      14:05

    • 6.

      Cómo crear un lector de finanzas

      16:23

    • 7.

      Colas y programador maestro

      15:06

    • 8.

      Cómo crear un trabajador

      21:54

    • 9.

      Cómo integrar un trabajador de postgres

      20:11

    • 10.

      Introducción de archivos de Yaml

      18:30

    • 11.

      Cómo crear un lector de yaml

      30:54

    • 12.

      Cómo mejorar nuestro trabajador

      28:21

    • 13.

      Cómo mejorar todos los trabajadores

      29:01

    • 14.

      Limpieza final

      7:13

    • 15.

      Bloqueo

      12:06

    • 16.

      Introducción a múltiples

      7:27

    • 17.

      Colas de procesamiento

      7:35

    • 18.

      Piscina de procesamiento

      10:40

    • 19.

      Mapa de piscinas multiprocesamiento

      4:05

    • 20.

      Argumentos diferentes múltiples

      4:45

    • 21.

      Elementos de verificación de múltiples procesos en la lista

      6:28

    • 22.

      Introducción para escribir programas asíncronos

      12:10

    • 23.

      Tareas asíncronas

      6:30

    • 24.

      Método de reunión

      7:39

    • 25.

      Cómo usar tiempos sincronizados

      3:12

    • 26.

      Cómo crear asíncronos

      3:00

    • 27.

      Cómo usar bibliotecas asíncronas

      10:28

    • 28.

      Declaración de espera sincronizada

      10:06

    • 29.

      Cómo combinar Async y multiprocesamiento

      12:14

  • --
  • Nivel principiante
  • Nivel intermedio
  • Nivel avanzado
  • Todos los niveles

Generado por la comunidad

El nivel se determina según la opinión de la mayoría de los estudiantes que han dejado reseñas en esta clase. La recomendación del profesor o de la profesora se muestra hasta que se recopilen al menos 5 reseñas de estudiantes.

154

Estudiantes

--

Proyecto

Acerca de esta clase

En este curso aprenderás cómo crear programas de múltiples roscos en Python, para que puedas hacer que tus programas se ejecuten aún más rápido.

Vamos a pasar por una introducción en la que provienen los posibles cuellos de botella de velocidad y cómo podemos resolver estos problemas, y luego vamos a profundizar directamente en el contenido técnico y construir un programa de múltiples roscos que reúne datos de Internet, analizamos y los almacenes en una base de datos local.

Puedes encontrar el código de conferencias en este repositorio de GitHub.

Conoce a tu profesor(a)

Teacher Profile Image

Max S

Power through programming

Profesor(a)

Habilidades relacionadas

Desarrollo Lenguajes de programación Python
Level: Intermediate

Valoración de la clase

¿Se cumplieron las expectativas?
    ¡Superadas!
  • 0%
  • 0%
  • Un poco
  • 0%
  • No realmente
  • 0%

¿Por qué unirse a Skillshare?

Mira las galardonadas Skillshare Originals

Cada clase tiene lecciones cortas y proyectos prácticos

Tu membresía apoya a los profesores de Skillshare

Aprende desde cualquier lugar

Ve clases sobre la marcha con la aplicación de Skillshare. Progresa en línea o descarga las clases para verlas en el avión, el metro o donde sea que aprendas mejor.

Transcripciones

1. Introducción a programación: programación actual: Hey ahi y bienvenido. Mi nombre es Max, fundador de codificación con Max y punto de control de datos. Y este curso, vamos a repasar la programación concurrente y paralela en Python. Vamos a aprender sobre cómo podemos escribir programas de subprocesos, cómo podemos escribir programas de multiprocesamiento, así como cómo también podemos escribir aplicaciones asíncronas. Y vamos a pasar, y en realidad vamos a construir un programa de subprocesos muy grande que va a leer datos de Yahoo Finance para obtener un proceso y luego subirlo a bases de datos. Y luego también vamos a escribir programas de multiprocesamiento para que podamos asegurarnos de que podamos aprovechar al máximo todos los núcleos de CPU disponibles en su máquina. Y luego también vamos a aprender sobre cómo podemos escribir aplicaciones asíncronas, cómo funcionan, y para qué puedes usar esas. Entonces con eso, espero verte por dentro. 2. Thread, multiprocesamiento, introducción de Async: Hey ahi, es max y bienvenido. En este módulo vamos a aprender sobre la programación concurrente. Ahora antes de saltar y escribir algunos programas geniales, vamos a obtener rápidamente un esquema y una visión general de lo que vamos a cubrir aquí para que todos estemos preparados y entienda en general lo que vamos a estar haciendo. Entonces, en primer lugar, el esquema de esta lección es primero sólo vamos a tener una breve introducción a la concurrencia, sólo mirando algunos ejemplos y por qué es incluso genial y por qué quizá queramos usarlo. Y entonces sólo vamos a entrar en algunas consideraciones de cosas que tenemos que tener en cuenta cuando pensamos en escribir programas concurrentes. ¿ Todo bien? Por lo general, cuando estamos escribiendo programas, es muy probable que estemos escribiendo programas secuenciales. Entonces una cosa pasa después de la otra. Y la mayoría de las veces estamos básicamente casi todo el tiempo hasta ahora está escrito sobre solo usar una sola CPU. Entonces eso significa que realmente no estamos haciendo pleno uso de todos los recursos que puedan estar disponibles para nosotros. Entonces echemos un vistazo a este ejemplo aquí. Digamos que nuestra máquina tiene cuatro núcleos y estamos ejecutando un programa Python. Y básicamente lo que estamos haciendo es que estamos calculando varias métricas. Tenemos archivo fuente de datos de alguna parte, y solo queríamos calcular algunas métricas diferentes. Entonces la forma en que podemos hacer que este programa se ejecute es primero calculamos la primera métrica, luego calculamos la segunda, luego calculamos la tercera, y luego lo guardamos todo en un archivo. Y si tenemos cuatro núcleos, eso significa que uno de nuestros núcleos es, va a estar ejecutando este programa y los otros van a estar sentados inactivos. Ahora por supuesto, hay otras consideraciones. Ya sabes, si estamos ejecutando esto en nuestra máquina personal porque podemos tener otras aplicaciones abiertas, etcétera, etcétera. Pero si estuviéramos en un entorno Cloud o algo así y en realidad tenemos más recursos de CPU disponibles, entonces podría ser que no estamos haciendo pleno uso de todos estos recursos disponibles. Entonces se podría hacer en su lugar es que podríamos tener un programa que calcule juego de métrica. Y he cambiado como los tamaños aquí para mostrar las diferentes métricas pueden tardar una cantidad diferente de tiempo en calcular. Entonces tienes métrica a, que va a estar funcionando en el primer núcleo. Y tenemos la métrica B, que se va a calcular al mismo tiempo en el segundo núcleo. Y luego tenemos la métrica SI, que se va a calcular al mismo tiempo en el tercer núcleo. Entonces debido a que estas métricas son independientes unas de otras, podemos calcularlas todas al mismo tiempo. No hay razón por la que tengamos que esperar a que termine uno. Y luego hacemos el segundo, y luego haremos el tercero. Podríamos calcularlos todos al mismo tiempo. Y luego una vez que cada uno de esos esté terminado, también podríamos simplemente escribirlos en un archivo. Y entonces si quisiéramos, podríamos fusionar todos los archivos juntos o algo que también podemos hacer es simplemente podemos reemplazar por lo general guardar en un archivo en su lugar por escribir en una base de datos. Entonces eso será calcular una métrica y luego la escribimos a la base de datos y luego, ya sabes, esa parte está hecha. Entonces en este caso, lo que tenemos aquí es que tenemos un programa más intensivo de CPU. Está pasando mucho cálculo, en el cuello de botella están realmente los cálculos. Y así en este caso, es bueno hacer uso de nuestros diferentes núcleos son diferentes recursos informáticos para que podamos hacer más cálculos al mismo tiempo. Pero también hay otros programas que podemos escribir donde no es tanto cálculo, pero en realidad mucho tiempo que pasa el programa solo está esperando respuestas de red. Entonces por ejemplo, algo que podríamos hacer es que pudiéramos solicitar, soy de algún lugar. Esto podría ser una API. Esto podría ser de un raspador web, puntos, ya sabes, golpeando sitio web. Pero de todos modos, solo estamos solicitando datos de algún lugar. Y entonces estamos esperando la respuesta sólo para volver a nosotros. Y entonces ahora tenemos los datos disponibles. Y entonces podemos o escribirlo en un archivo, por ejemplo, o podemos escribirlo en una base de datos y correr a una base de datos en realidad es entonces enviar la solicitud para decir, vale, por favor escribe esto y luego esperar hasta la respuesta de la red. Sí. Está bien, está escrito. Y luego si estamos haciendo esto por múltiples piezas de datos y tal vez nosotros, solicitamos la primera pieza de datos y luego esperamos la respuesta a ellos, lo escribimos y luego podemos solicitar la segunda pieza de datos, esperar la respuesta, y luego escribirlo. Y la propia escritura tiene de nuevo, mandando fuera de la derecha y luego esperando a que se lo reconozca. Entonces en este caso, solo estamos pasando mucho tiempo esperando que sucedan las cosas. Estamos pasando mucho tiempo esperando solo señales de reconocimiento. Sí. Aquí tienes tus datos. De acuerdo, por fin está disponible para nosotros, como cómo ser transferido a través de la red. O Aquí vamos, sí, Los datos ya se han guardado en la base de datos. Entonces podemos tener, en este caso es que podemos tener múltiples hilos. Por lo que aún tenemos todo funcionando en una sola CPU en un solo núcleo. Pero tenemos múltiples programas concurrentes ejecutándose en el mismo núcleo. Entonces podemos tener un hilo principal, que básicamente, si no quiere hacer otra cosa, puede haber algunas cosas pasando de antemano, pero en realidad solo puede comenzar Oliver child, hilos infantiles. Y entonces lo que hará el primer hilo infantil es que va a solicitar datos. Y mientras está esperando, el segundo hilo puede entonces solicitar es theta. Y luego cuando entren los datos, entonces puede, el primer hilo puede decir, vale, ahora tengo mis datos y voy a escribir esto en una base de datos. Y luego pasa tiempo esperando de nuevo. Y mientras un hilo está esperando la comunicación de red, para los reconocimientos de red, el otro hilo puede estar haciendo su trabajo. Y así se puede ver aquí. Tenemos dos hilos que se están ejecutando de forma concurrente, todo el tipo de desconexión. Uno solicita los datos y cuando está inactivo, cuando solo está esperando a que la red le dé una respuesta, el otro hilo puede estar ejecutándose. Ahora hay otro ejemplo de cosas que pueden suceder es que podemos tener mucha escritura en bases de datos. Entonces una cosa aquí, por supuesto cómo podemos hacer es que podemos usar hilos, nuevo para tener múltiples hilos, cada uno de ellos derechos a una base de datos. Y mientras ese hilo está esperando que la base de datos dé un acuse de recibo, el otro hilo puede iniciar su derecho, etcétera. Ahora también podemos usar un programa asíncrono donde básicamente mandas el derecho y luego continúas con el programa. Y cada vez que obtienes el acuse de recibo, entonces como que vuelves a esa parte completada y sigues adelante con el programa. Por lo que tu programa no está bloqueado por estos tiempos de comunicación IO de red, sino que en su lugar solo escribes en la base de datos. Como se puede ver en el lado derecho aquí. Entonces escribimos a la base de datos, y mientras esperamos el acuse de recibo, sólo iniciamos el segundo derecho a tal vez una base de datos diferente y luego incluso podemos escribir tal vez a una tercera base de datos. Y así todo esto está pasando y en segundo plano, ya sabes, estamos esperando hasta que escuchemos un acuse de recibo de cualquiera de las bases de datos a las que realmente hemos escrito. Y siempre que obtengamos ese reconocimiento, entonces podremos continuar con esa parte del programa. Y así que realmente esto nos ayuda a ahorrar mucho tiempo que de otra manera pasaríamos simplemente sentados inactivos esperando que ocurriera la comunicación de red. Ahora puede que esto no parezca un gran problema porque, ya sabes, las velocidades de internet pueden ser muy rápidas. Pero si estás haciendo mucha comunicación en red como si estuvieras escribiendo un montón de valores. Por lo que si estás enviando un montón de solicitudes, tu programa puede estar pasando mucho tiempo solo sentado por ahí inactivo, esperando. Y así tener esta opción de usar hilos para tipo de hacer cosas mientras estamos esperando o poder hacer uso de múltiples núcleos de CPU si tenemos operaciones intensivas de cómputos, esto realmente puede ser un gran beneficio para nosotros y puede acelerar nuestros programas dramáticamente. Ahora bien, hay por supuesto, algunos inconvenientes y consideraciones que tenemos que hacer aquí. Entonces lo primero que necesitamos ser conscientes como Python tiene algo conocido como un bloqueo de intérprete global, lo que básicamente significa que solo podemos estar ejecutando un hilo a la vez. Entonces puedes ver aquí si volvemos al ejemplo, si miramos al niño uno y al hilo hijo a hilo hijo salvaje, uno está iniciando la solicitud de los datos. realidad, el capítulo 2 está inactivo. No está iniciando su propia petición. Es sólo reloj sostenido. objetivo uno está inactivo donde está esperando. Ese hilo infantil T2, por ejemplo, puede comenzar a trabajar. Entonces no son exactamente concurrentes, pero los hilos están tomando turnos. Y cada vez que uno está inactivo, otro puede saltar y tomar ese tiempo de CPU. Y así cada vez que algo está ocioso, eso es como cuando pueden entrar. Entonces no es perfecta concurrencia, pero por supuesto seguimos teniendo aceleraciones dramáticas porque no tenemos que pasar todo este tiempo esperando y mientras esperamos, no estamos haciendo nada más. Ahora también hay un tema importante. Tenemos que pensar en que no todo puede ser seguro para hilos. Entonces, básicamente, los medios seguros para subprocesos es que está bien que múltiples hilos estén tratando con una determinada entidad. O nuestros hilos están tratando con datos de una manera que no interfiere con otras amenazas. Ahora, una forma en la que podemos ir por la seguridad de los hilos es mediante el uso de bloqueo. De otras maneras también simplemente escribir programas seguros para subprocesos que no conducen a que ocurran cosas raras cuando varios hilos están tratando de acceder, por ejemplo, compartir una pieza de datos. Entonces una de esas cosas que podemos conseguir si no tenemos seguridad de hilo es algo llamado condición de carrera. Ahora esto es algo que verás aquí en hilos, pero también puede surgir cuando sepas que estás aprendiendo sobre bases de datos. Pero básicamente una condición de carrera es cuando dos programas o entidades o hilos separados, en este caso, intentan acceder y modificar la misma pieza de datos o incluso simplemente usan los mismos datos. Entonces por ejemplo, digamos que tenemos dos hilos que ambos hacen uso de una variable a. Y el hilo uno lee la variable y luego la modifica y al mismo tiempo, o poco antes o poco después de hilo para leer también a la variable y luego le escribe. Y hay muchas cosas diferentes que pueden suceder. Entonces, por ejemplo, digamos que cada uno de estos hilos simplemente incrementando la variable. Si nuestros dos hilos los leen casi simultáneamente, entonces ambos van a ver el mismo valor. Y luego un hilo, un tipo de pone su resultado n y simplemente lo incrementa por uno. subproceso 2 no habrá visto ese nuevo valor, pero habría visto el valor anterior. Y así cuando lo incremente en uno, sólo en total va a ser incrementado en uno en lugar de en dos porque ambos lo leen en un momento similar antes de que uno de los otros terminara su operación. Y entonces por supuesto puedes tener otras variaciones de básicamente el mismo problema. Donde o sobrescribes la variable, realizas alguna operación descendente, por ejemplo, la suma o multiplicas y luego no la usas hacia abajo más adelante. Pero debido a que los hilos están pasando al mismo tiempo, es muy difícil para nosotros saberlo exactamente. Es básicamente imposible para nosotros saber a qué hilo va a estar accediendo al principio, sobre todo tipo de conocerlos a través de una corrida diferente del mismo programa. Entonces si volvemos a ejecutar nuestro programa, esto puede llevar a resultados impredecibles porque a veces un hilo lo convierte en el primero y a veces otro hilo puede llegar primero. Y a veces podemos tener una condición de carrera. A veces podemos no porque también son factores externos en juego. Y así. Las condiciones de carrera pueden llevar a resultados muy impredecibles. Y así que tener esto en cuenta es muy importante que si tienes datos compartidos o algo por el estilo, que siempre tengas que pensar. seguridad del hilo es el programa que estoy escribiendo puede interferir consigo mismo. Y si estás usando otros módulos o bibliotecas en Python, y algunos de ellos dirán específicamente esta entidad, por ejemplo, esta clase que estás usando es segura para subprocesos o esta clase no es segura para subprocesos. Y así hay que ser consciente y cuidadoso con ellos porque esto puede llevar a errores muy, muy raros, complicados y complicados y confusos que son difíciles de reproducir y muy difíciles de rastrear. Entonces lo otro a considerar es antes que nada hablar de hilo. Específicamente, los hilos se ejecutan en un solo núcleo de CPU y todos comparten la misma memoria, razón por la cual tenemos este tema de seguridad de subprocesos y condiciones de carrera. Y también hay una pequeña sobrecarga asociada con solo cambio de hilo entre los diferentes hilos, así como solo manejo de los hilos en la autocreación, desgarro de los hilos. En tanto que para el multiprocesamiento y lo que tenemos es que tenemos diferente el mismo programa que se ejecuta en diferentes núcleos de CPU, o la misma parte de este programa que se ejecuta en diferentes núcleos de CPU. Y así en realidad en este caso, no tenemos memoria compartida. Cada proceso tiene su propio intérprete de Python y su propio bloqueo de intérprete global. Entonces claro, eso es genial porque no tenemos que tener algunos de estos temas que tenemos con amenazas, por ejemplo. Pero también hay más memoria. También hay más gastos generales asociados con esto. Entonces uno de esos es reduplicar mucho el uso de la memoria. Y solo hay mucha más memoria que necesita ser utilizada para crear y replicar todos estos diferentes procesos a través de los diferentes intérpretes. Y apenas sobre la concurrencia en general, es muy cool y puede ser extremadamente útil en rápido. También queremos asegurarnos de que los programas que estás escribiendo realmente van a valer la pena escribir y de manera concurrente. Porque escribir y depurar programas concurrentes puede llegar a ser muy complejo y a veces se hace difícil encontrar problemas en tu lógica o depurar ciertos problemas debido a que ocurre toda esta concurrencia. Entonces sí, Con considerar la concurrencia, definitivamente podemos conseguir aceleraciones increíbles. Pero también recuerda que no todos los programas tienen que ser concurrentes. Y está totalmente bien, ya sabes, simplemente seguir escribiendo muchos programas secuenciales. Pero entonces te darás cuenta como, Oh Dios mío, estoy pasando tanto tiempo esperando que todo esto no funcione. Yo o, realmente puedo hacer uso de multithreading aquí, o no hay razón para que yo calcule estas 80 métricas secuencialmente. Simplemente voy a usar el multiprocesamiento y hacer uso de cuatro o dos u ocho o pasar por alto muchos núcleos que tienes disponibles ya sea en tu máquina o en el entorno Cloud y solo voy a acelerar el proceso. Por lo que definitivamente están escribiendo situaciones para usarlo. Pero también hay, ya sabes, no tenemos que escribir cada programa de forma concurrente. Entonces solo ten eso en cuenta porque la concurrencia sí agrega complejidad a la escritura y a la lógica y también a la depuración. 3. Enlace en Python: Muy bien, así que sigamos adelante y en realidad escribamos nuestro primer programa concurrente. Vamos a empezar con el enhebrado. Ahora voy a estar usando PyCharm para esto, pero puedes por supuesto, seguir adelante y siéntete libre de usar cualquiera que sea tu entorno de codificación favorito. Me gusta mucho usar PyCharm cuando tenemos múltiples archivos, que en realidad terminaré, ya sabes, yendo hacia la parte posterior de a medida que avanzamos por el subproceso. Entonces sí, bastante como trabajar con gráfico circular para esto. De lo contrario, ya sabes, si estoy haciendo una prueba rápida y prototipado y necesito manipular o tipo de querer mirar atrás a una gran cantidad de datos que se crearon a lo largo del curso de un programa o simplemente una especie de juego con las cosas. Para eso, usualmente me gusta usar una araña o Cuadernos Jupyter. Pero aparte de eso, disfruto bastante usando PyCharm. De nuevo, esto depende completamente de ti. Por lo que acabo de crear una carpeta en mi escritorio aquí donde vamos a estar guardando todo nuestro trabajo. Voy a crear un nuevo archivo y llamar a esta casilla. Yo sólo voy a llamar a esto mi principal, pero puedes llamarlo como quieras siempre y cuando tuviera la extensión de punto py. Y voy a estar haciendo algo aquí que probablemente veas mucho en los programas de Python. Y vamos a empezar definiendo una función principal. Y vamos a hacer pasar aquí, lo que simplemente nos deja básicamente decir que volveremos a esto más adelante. Entonces ahora mismo no va a hacer nada. Aquí vamos a tener la sintaxis. Si guión bajo, guión bajo, nombre, guión bajo, guión bajo es igual a. Y entonces tenemos subrayado. Subrayado, subrayado, subrayado, subrayado principal, subrayado. Y luego vamos a ejecutar la función principal. Ahora, básicamente, lo que significa esta sintaxis es que si este programa se ejecuta directamente, no cuando se importa ni nada, solo uno este programa se ejecuta específicamente. Ahí es cuando se ejecutará esto. De lo contrario, si importamos esto, entonces no se ejecutará. Entonces esto es sólo la sintaxis de ojos de coordenadas. A mí me gusta bastante. Y es probable que lo veas en muchos programas de Python. Por supuesto, no es completamente necesario, pero es un poco agradable si quieres probar el código que estás escribiendo aquí mismo cuando un poco quiere ejecutarlo. Pero de lo contrario, si quieres importarlo, no quieres que se ejecute. Muy bien, entonces tenemos nuestra función principal aquí. Y básicamente lo que vamos a estar haciendo es que vamos a estar escribiendo, bueno, dos funciones. En la primera función se va a calcular la suma de cuadrados. Entonces lo vamos a llamar def, calcular cuadrados de suma y va a tener una entrada. Sólo podemos decir n por ahora. Eso lo definimos en un segundo. Y nuestra segunda función es simplemente ir a dormir un poco. Y entonces sólo vamos a proporcionar, y aquí la entrada y segundos por cuánto tiempo nos gustaría que durmiera. Y lo definimos en un segundo también, porque primero solo necesitamos importar el módulo de tiempo, lo que nos permitirá hacer este durmiendo. Entonces quiero decir funcional modificar eso en un segundo. Entonces para dormir un poco, todo lo que vamos a hacer aquí es que vamos a llamar a la función del sueño. Y sólo vamos a dormir por tantos segundos. Para el cálculo de suma de cuadrados, sólo vamos a tener una variable de cuadrados de suma que vamos a iniciar a 0. Vamos a tener un bucle for para I en rango. Y, y en cada iteración solo vamos a tener que sumar nuestra suma de cuadrados a este número al cuadrado. Y luego al final, solo imprimamos aquí la suma de las casillas. ¿ De acuerdo? Entonces ahora en nuestra función principal, Vamos a seguir adelante y tener 24 bucles. Diré para mí en el rango cinco, sólo vamos a ejecutar el cálculo de suma de cuadrados. Y esta va a ser nuestra aportación aquí. Y vamos a tener una segunda función que va a decir para yo en rango, partiendo de una, yendo al sexo. Entonces en realidad dormimos la primera iteración, vamos a llamar un poco a dormir. Y vamos a tener nuestro valor, escucho. Y también vamos a tener temporizadores que queremos configurar. Entonces vamos a medir los tiempos de cálculo de nuestro programa. Y también podemos usar el módulo de tiempo para esto. Por lo que vamos a tener nuestra hora de inicio de cálculo se va a definir como la marca de tiempo actual en este momento. Y luego una vez hecho esto, vamos a decir calcular suma de cuadrados tomó. Y luego nos vamos a tomar el tiempo en el momento actual menos la marca de tiempo que tenemos en este momento. Y primero salvamos aquí nuestra variable. Ahora, esto nos va a dar una salida con muchos números decimales. Entonces lo que vamos a hacer en su lugar es que vamos a usar el método redondo, y sólo vamos a redondearlo a un decimal, lugar para conseguir este tipo de reducido un poco, un poco más limpio. Y luego lo que vamos a hacer por los pequeños de sueño, vamos a hacer algo similar. Vamos a dormir, empezar. El tiempo, que también sólo va a ser el rastreo, el tiempo en este momento, guardándolos en una variable. Y entonces otra vez aquí vamos a estar durmiendo. Tomó la hora actual menos la hora de inicio. Eso es lo que tardó. Y tener realmente los cálculos toma algún tiempo. No sólo te vamos a poner en el ojo, sino que sigamos adelante y hagamos que este sea yo más 1, en primer lugar. Y entonces también lo vamos a multiplicar por 1 millón, sólo para que lleve un poco de tiempo. Ahora podemos ejecutar esto. Simplemente, por ejemplo, haciendo clic en el Ejecutar aquí. Y va a, bueno, empezar a ejecutar el programa secuencial para nosotros. Y así podemos ver aquí actualmente la suma de cuadrados está en el trabajo y tomó alrededor de siete segundos, redondeados a un decimal que podemos ver aquí. Y ahora nuestro programa sólo va a estar durmiendo iterativamente. Entonces 1 segundo, 2 segundos, tres segundos, cuatro segundos, cinco segundos. Y luego al final de eso, vamos a ver, de acuerdo, así que todo ese proceso tomó 15 segundos. Por lo que en total, nuestro programa tardó alrededor de 21 segundos o 22 segundos. Tienes 15 aquí más siete. Por lo que siete de esos fueron para el cálculo y 15 de esos fueron para el sueño. De acuerdo, entonces este es un programa secuencial. Entonces sigamos adelante y tratemos de agregar alguna concurrencia aquí. Vamos a usar el subproceso para esto. Entonces vamos a importar el subproceso. Ahora, lo bueno es que el enhebrado es en realidad parte de la instalación estándar de Python. Por lo que realmente no tienes que pip instalar nada más. Simplemente puedes importarlo directamente. Ahora para cada uno de estos bucles aquí, ahora vamos a reemplazar esto en su lugar por un hilo. Entonces lo vamos a hacer en cada uno de estos casos, es que vamos a crear un hilo y lo llamaremos t, solo va a ser nuestra variable corta para hilo, amenazando hilo de punto y otras varias variables que necesitamos definir aquí. El primero es el objetivo, que va a ser la función que se necesita ejecutar. Y para eso, para este caso va a ser calcular suma de cuadrados. Nota No voy a poner los paréntesis al final. Es solo el nombre de la función porque aún no queremos llamarlo. Esta es un poco la referencia a la función. Entonces también podemos proporcionar los argumentos a nuestra función. Tenemos una palabra clave separada aquí, args, y esto espera una tupla. Entonces como solo tenemos un argumento de entrada, vamos a tener nuestro valor de entrada aquí. Y luego vamos a o.Vamos a tener nuestro, vamos a definir nuestro máximo valor va a ser esto aquí, sólo para tenerlo y no ser un poco más corto. Y así nuestra tupla de entrada va a ser esto, pero dice que tiene que ser una tupla. Tenemos que poner una coma extra aquí para asegurarnos de que sea una tupla de talla uno. Entonces vamos a comentar esto. Y entonces vamos a hacer lo mismo aquí. Vamos a crear un hilo. Y vamos a tener como objetivo el sueño un poco de función. Y el argumento de entrada que van a proporcionar es este ojo aquí. Y vamos a renombrar esto a segundos. No necesitamos saber que estos nombres son los mismos. No necesitamos tener esto. Esto sólo hace un poco más agradable de leer. Entonces voy a renombrar esto a segundos otra vez, hacer de esto una tupla de una. Y vamos a comentar esto. Ahora, si ejecutamos esto, será un poco sorprendido porque en realidad nada los va a tener bastante todavía. Y la razón de esto es que realmente necesitamos iniciar los hilos. Entonces lo siguiente que tenemos que hacer es por cada hilo tendrá que llamar a t dot. Inicio. Al igual que esto. Ahora podemos ejecutar esto y todavía vamos a conseguir un poco de un resultado raro. Entonces sigamos adelante y veamos esto. Entonces note cómo nuestro programa tipo de continuó. Y luego tenemos las salidas de impresión. Y entonces esto está aquí. Y luego teníamos las sumas impresas. Entonces esto obviamente no es cuánto tiempo tardó tu programa porque aún hay otras cosas en marcha. Pero esto es solo porque los hilos se están ejecutando simultáneamente. Entonces lo que queremos es lo que queremos que el programa sea bloqueado para esperar hasta que todos los hilos terminen. En este punto. Aquí es cuando todos los hilos necesitan terminar. Y luego queremos imprimir cuánto tiempo tardó esto. Entonces para hacer eso, vamos a configurar una, otra variable. Tener que sea una lista. Vamos a hacer un seguimiento de cada uno de estos hilos y luego solo asegurarnos de que nuestro programa se bloquee hasta que estén todos terminados. Por lo que sólo llamaremos a esta variable amenazas actuales. Y de nuevo, puedes llamarlo como sea. Y cada vez que creemos un hilo, vamos a anexar aquí el hilo para que podamos referirlo más adelante. Ahora vamos a recorrer nuestra lista. Y para cada elemento, que es el hilo aquí mismo, vamos a llamar a dot join. Ahora lo que hace dot join es que bloquea la ejecución hasta que se haga este hilo. Entonces estamos iterando sobre esto y básicamente estamos llamando a dot join, lo que significa que no se permite que nada suceda hasta que termine ese hilo. Por lo que no puede ir más allá de esto, básicamente. Entonces hemos hecho esto por aquí. Ahora sigamos adelante y hagamos lo mismo aquí. Entonces, solo reutilicemos esta variable y reutilicemos esto. Déjame poner esto aquí. Y de nuevo, vamos a llamar a dot join para asegurarnos de que nuestro programa esté bloqueado. Y luego esperamos a que esto termine hasta que luego ejecutemos esto. Entonces si seguimos adelante y ejecutamos esto ahora, podemos ver ahora, de acuerdo, así que nuestra ejecución en realidad va como se esperaba. Y aquí ahora tenemos nuestro sueño, vale, así que algo interesante que notar. En primer lugar, escucha este un poco más rápido, pero, ya sabes, realmente nada por lo que emocionarse. Y realmente esto es solo porque esto es, este es un método intensivo de cómputación. Y así que la mayoría de las veces realmente no vas a estar recibiendo ninguna mejora de rendimiento en términos de como solo cosas de cómputación aquí. Entonces realmente nada que sea todo fascinante aquí. Y si quisiéramos acelerar las mejoras en esta sección, entonces vamos a necesitar ir al multiprocesamiento ya que podemos usar diferentes núcleos. Pero aquí porque cada tipo de hilo solo puede estar funcionando a la vez y esto es intensivo en CPU, realmente todos estos cálculos, no hay mucho IO pasando. Um, entonces, ya sabes, simplemente como que básicamente pasa secuencialmente de todos modos. Pero lo fresco está aquí, y el sueño es que la enfermedad es un ejemplo muy, muy sencillo. El sueño ocurre en un nivel de hilo, por lo que se puede ejecutar un hilo diferente mientras cada uno de estos hilos está sentado inactivo. Entonces en lugar de tomar un tiempo total de 15 segundos, que es lo que tomó nuestro programa secuencial. Sólo toma cinco segundos, que es básicamente el sueño más largo que tuvimos. El máximo aquí es de cinco. Entonces podemos ver en este caso, por supuesto, este es el ejemplo muy, muy básico. Vamos a ser mucho más útiles para no dormir ni programar. Pero en cambio, ya sabes, si esto es algún tipo de conexión de red, como hacer una solicitud de API, escribir en una base de datos desde llegar de una base de datos o, ya sabes, lo que sea, cualquier cosa pesada en la red IO que solo pasa donde simplemente están nuestros hilos, donde nuestro programa pasa mucho tiempo inactivo, solo esperando la comunicación de red y tal vez el servidor del otro lado haga lo suyo y luego envíe de vuelta la respuesta. Ahora hemos visto como los fundamentos de crear hilos aquí para diferentes funciones, pero quería mostrarles algunas otras cosas que creo que son interesantes. Entonces lo primero es lo que habría pasado si en lugar de llamar a unirse al final aquí, su lugar lo llamaríamos aquí. Entonces sigamos adelante y llamemos a t dot únete aquí. Y vamos a seguir adelante y volver a ejecutar esto. Entonces, ¿qué pasa en este caso? Ahora éste sigue llamando al unirse al final aquí. Pero de nuevo, esto es como una CPU. El funcion o intensivo entre comillas por supuesto, pero ya sabes, CBO enfocado. Entonces se puede ver aquí básicamente siete segundos, que es exactamente lo que teníamos antes. De nuevo, aquí no esperamos ningún cambio. Pero en este caso, lo que pasa es la llamada Join aquí significa que en realidad la ejecución está bloqueada. No, este bucle no continúa. Se bloquea la ejecución hasta que termine este hilo. Entonces ahora estamos volviendo a los 15 segundos que teníamos antes. Porque no estamos iniciando todos estos hilos y dejándolos correr y luego bloqueando el programa al final hasta que todos estos hilos estén hechos. Pero en cambio, iniciamos un hilo y luego bloqueamos toda la ejecución hasta que esa amenaza se haga. tanto que antes empezamos todos los hilos y luego bloqueamos la ejecución hasta que todos los hilos hayan hecho. Por lo que se puede ver aquí incluso sólo una ligera sintaxis de tener el join aquí en lugar de aquí. En este caso, un impacto muy grande en nosotros. Ahora, hay otra cosa que quería mostrarles. Si sacamos las declaraciones conjuntas, que en realidad es lo que no habíamos empezado. Y si solo recordamos, si volvimos a ejecutar esto, como que conseguimos esta cosa rara donde nosotros, ya sabes, el tipo de programa hace lo suyo, el hilo principal aquí. Y ahora en realidad obtenemos toda la impresión y en realidad el sueño también está sucediendo para estos diferentes hilos. Entonces tenemos 10 hilos diferentes corriendo cinco de aquí. Bueno en realidad 11 porque este va a ser nuestro principal aquí, el programa principal, creamos cinco hilos extra aquí. Cinco hilos extra aquí. Y éste termina como básicamente, ya sabes, haciendo lo suyo, no está bloqueado por esto, hace estas impresiones, y entonces ésta se está ejecutando. Y está imprimiendo la suma de cuadrados. Y mientras tanto, estos cinco hilos apenas están durmiendo. No estamos imprimiendo ningún sentido, así que no lo vemos. Entonces algo que también puedes pasar es que puedes agregar una mosca de daemon aquí y establecer que esto sea cierto. Y aquí podemos hacer lo mismo. Ahora esto se vuelve interesante cuando ejecutamos esto. Porque lo que pasa es que corremos por el hilo principal y una vez que termina el hilo principal, todo el programa se detiene. Entonces lo que significa aquí la bandera daemon es que una vez que se hace el hilo principal, todos Damon banderas Autor. Y no importa si terminan o no. Si un hilo no es un hilo daemon, entonces cada hilo necesita terminar. Todo no Damon amenaza con terminar antes de que todo el programa pueda terminar. Pero los hilos Damon no necesitan terminar para que el programa termine. Una vez que se hace el hilo principal, entonces si algún hilo daemon o se queda, realmente no importa. Eso no impide que el programa termine. Entonces esto es algo interesante, ya sabes, dependiendo de la situación que puedas o incluso querías o no la quieres. Pero solo ten en cuenta que tener aquí el vuelo de declaración significa que estos hilos, si el programa termina, el programa principal termina. Y si algo es un hilo daemon, entonces eso significa que no terminará, solo se detendrá, el programa está hecho. tanto que si tenemos la bandera de Daymond a falso, entonces estos hilos también necesitan terminar hasta que todo el programa pueda terminar, que es exactamente lo que teníamos antes. Entonces mientras esto se está ejecutando, déjame simplemente volver a poner esto. Ahora hay por supuesto una cosa interesante que podemos usar con las articulaciones. Si nos hemos sumado, de nuevo, la declaración conjunta significa que el hilo que cada uno de estos hilos a los que estamos llamando el join necesita terminar antes de que podamos continuar en este punto, porque básicamente está bloqueando hasta que se hagan todos esos hilos. Entonces si volvemos a ejecutar esto, a pesar de que esto sean hilos de Damon, porque estamos llamando a estas declaraciones conjuntas que están bloqueando una mayor ejecución. Básicamente aseguramos que los programas terminen. Por lo que podemos ver que tipo de volver a los resultados anteriores que hemos tenido. Y podemos llevar esto aún más allá para decirlo, en lugar de repasar los hilos de Oliver, tal vez sólo bloqueamos hasta que se hagan los tres primeros. Y así nuestro sueño aquí. Esperaríamos que esto fueran tres segundos ya que los otros dos son amenazas Damon. Y así puede como seguir adelante. Pero los tres primeros realmente van a estar durmiendo y van a estar bloqueando la ejecución. Entonces puedes ver aquí eso es exactamente lo que obtenemos. Los tres primeros están bloqueando la ejecución una vez que finaliza el tercer hilo de esta sección, que es un sueño durante tres segundos, el contingente del programa continúa, termina, y los únicos hilos restantes son hilos Damon. Por lo que todo el programa está hecho. 4. Crea una clase de rosado: Muy bien, así que acabamos de terminar de escribir nuestro primer tipo de programa con hilos. Ahora lo que vamos a hacer es que vamos a abrazar un poco y en realidad vamos a convertir estos en clases. Y te mostraré cómo realmente podemos usar clases para enhebrar a. Entonces para hacer esto en primero realmente va a crear un nuevo directorio. Y aquí sólo vamos a tener que nuestros diferentes trabajadores son hilos diferentes solo para, ya sabes, tener alguna estructura. Y entonces aquí, esta va a ser nuestra suma o calcular suma de cuadrados función básicamente se va a poner en una clase para que podamos reutilizar. No tiene tanto sentido para este caso de uso, sino para otros fines más generales. Entonces esto va a ser r al cuadrado, algunos trabajadores punto py, si acaso queremos tener varios. Y esta de aquí vamos a tener otra que va a ser tu función de sueño. Entonces vamos a tener que ser r, Sueño ser marcadores. Y también voy a y, y subrayado, subrayado init, subrayado, guión bajo punto py archivo, que va a convertir este directorio aquí para mí en un módulo Python del que puedo importar. Entonces ni siquiera necesito poner nada aquí, pero sólo me va a permitir importar desde este directorio. Está bien, así que sigamos adelante y empecemos con r al cuadrado. Algún trabajador. En primer lugar vamos a importar threading. Y luego vamos a crear una clase. Va a ser r trabajador de suma cuadrada. Y este trabajador va a heredar de la amenaza de punto de enhebrar. Entonces es una especie de heredar de la clase de hilo aquí. Y luego vamos a definir la inicialización de la clase. Y vamos a usar esta palabra clave super. Por lo general, solo lo autocompleta. Entonces ahí vamos. Y vamos a por inicialización de clase padre, sólo vamos a usar el super método. Ahora, el super método aquí, sólo definimos la clase que tienen los padres que queremos inicializar. Y luego nos llamamos yo aquí y luego llamamos punto en él. Y básicamente todas las clases padre de las que hereda esta clase entonces se inicializarán. Por lo que no necesitamos realmente inicializar cada clase de padre individual por separado. Podemos simplemente llamar a la inicialización completa de todas las clases de padres así, lo cual es bastante conveniente. En este caso, claro que sólo tenemos una clase, pero, ya sabes, si tuviéramos múltiples aquí y solo quisiéramos inicializarlos sin más problemas. Entonces podemos hacerlo así. ¿ Todo bien? Y entonces lo que tenemos aquí es que vamos a tener una suma calculada de cuadrados. Entonces nos vamos a hacer cargo de esto. Y debido a que es una clase, tenemos que meternos aquí auto. Y así todo lo que este método aquí va a hacer es que va a calcular la suma de los cuadrados exactamente de la manera que lo teníamos antes. Ahora en realidad hay dos formas diferentes en las que podemos hacer esto. Una forma es que podemos dejar aquí la entrada para que solo podamos proporcionarla a través de este método de clase. O la otra forma en que podemos hacerlo es que podemos tener que sea parte de la inicialización de la clase. Y entonces podemos establecer un atributo de la clase. Y entonces no tenemos una entrada aquí. Y está húmedo, sólo hace referencia al atributo. Ahora en este caso, realmente no importa tanto. En realidad puede ser más limpio usarlo aquí. Pero en lugar de simplemente tenerlo así es en realidad una especie de sintaxis que me gusta bastante. Porque entonces, ya sabes, si estás escribiendo uno más métodos, terminan teniendo como muchos parámetros de entrada. Y así de esta manera, solo puedes inicializar tus valores. Tu IQ solo puede inicializar tu clase para todos los valores y luego solo hacer referencia a parámetros internos en lugar de tener que pasarlos a todos estos métodos diferentes si llega a ese punto. Entonces en realidad vamos a usar este método. Y ahora hay algo más que podemos hacer, que es que podemos hacer estrella, quarks estelares. Y entonces lo que esto significa es que esto va a ser un mapeo de pares de valores clave para argumentos de palabras clave adicionales que quizás deseemos pasar. Esto podría ser, por ejemplo, nombre igual, y luego sea cual sea el nombre de entrada que va a ser. Y entonces podemos tener, ya sabes, como persona. No sé de dónde vino eso, pero, ya sabes, solo puedes tener todos estos otros parámetros de entrada. Y en lugar de definir cada uno de los tipos de montaña de dejarlo abierto, en realidad podemos tener que esto sea esta estrella, palabra clave estrella, argumentos. Y A lo mejor hay parámetros que realmente queremos pasar al subproceso que queremos establecer. Y así podemos simplemente pasar estos argumentos de palabras clave más abajo aquí. Y así de esta manera, es realmente agradable porque podemos proporcionar todos estos parámetros de inicialización que simplemente se pueden transmitir a los métodos padre o también podemos usarlos nosotros mismos. Ahora, algo más, claro, que tenemos que hacer es que tenemos que empezar nuestro hilo. Entonces tenemos que hacer eso para asegurarnos de que en realidad empiece a correr. Ahora lo interesante es cuando iniciamos el hilo, realmente si quieres hacer el cálculo, tenemos que ponerlo en el método de ejecución. Entonces si tenemos un método de ejecución y si llamamos self.age star porque estamos heredando de la clase de hilo. Se iniciará el hilo y apenas empezaré a ejecutar el método de ejecución. Y así podemos sobrescribir el método de ejecución que heredamos de la clase de hilo para hacer el running por nosotros. Entonces en este caso en realidad lo que vamos a hacer es que sólo vamos a calcular la suma de cuadrados. Entonces en realidad ni siquiera vamos a llamar a este método. Simplemente vamos a crear la clase y luego va a realizar la carrera por nosotros. De acuerdo, así que una pequeña cosa más de sintaxis aquí. Sólo voy a agregar un guión bajo porque sólo para indicar que es una especie de método interno que vamos a estar usando, ya sabes, internamente en clase. Está bien, así que esta va a ser nuestra clase de enhebrado, 4 al cuadrado, algún marcador. Ahora sigamos adelante y hagamos lo mismo por nuestro Yorker dormido. Por lo que de nuevo aquí vamos a importar threading. Vamos a crear el marcador somnoliento clase, que va a heredar del hilo de muelle de enhebrado. Vamos a inicializar la clase e inicializar la clase padre. Y vamos a permitir argumentos de palabra clave que vamos a pasar a las inicializaciones de las clases padre. Y entonces también aquí donde podemos poner es segundos por cuánto tiempo? Por cuantos segundos queremos que esto duerma, que es, por supuesto, estaremos usando un segundo. Entonces aquí vamos a tener nuestro sueño. Una pequeña función, que sólo va a llamar tiempo de sueño punto en la variable segundos. Ahora te darás cuenta de una bonita cosa cool up PyCharm hizo aquí para mí es que no importamos el libro del módulo de tiempo porque, ya sabes, está fácilmente disponible. Quieres un tipo de reconocer esto como una opción que lo estábamos usando, en realidad hizo lo importante para mí, pero de lo contrario por supuesto, ya sabes, asegúrate de importar el módulo de tiempo. Muy bien, entonces vamos a dormir por el número de segundos que pasamos en la inicialización aquí. Y entonces sólo vamos a anular el método de ejecución para llamar a dormir, un método literal que acabamos de definir aquí. Está bien, así que volviendo a nuestra función principal, ya no necesitamos el enhebrado y puesto aquí, creo que nos volverás a ver. Vamos a, de trabajadores punto trabajadores durmientes, vamos a importar a nuestro trabajador de la ciudad. Y de los trabajadores punto cuadrado de algún trabajador que vamos a Concord R-cuadrado algún trabajador. De acuerdo, así que ahora podemos reemplazar la creación de este bucle aquí en su lugar con solo inicializar nuestra clase. Entonces vamos a hacer que nuestro trabajador soñoliento sea una instancia de trabajador soñoliento. Y vamos a querer unas esperanzas que vayan por debajo. Aquí. Tenemos r al cuadrado, algún trabajador, que va a ser una instancia de la raíz cuadrada algún trabajador. Y vamos a tener el valor máximo aquí como parámetro de entrada. Y lo que vamos a hacer ahora para el join es para los hilos actuales. Vamos a renombrar esto a bultos de trabajadores actuales. Técnicamente lo mismo que tenemos aquí. Vamos a hacer un seguimiento de nuestro trabajador que hemos inicializado aquí. Y de nuevo, sólo vamos a llamar al método join on aquí a especie de bloque hasta esta ejecución de esto hecho. Y luego vamos a hacer lo mismo por nuestro trabajador soñoliento. Y aquí están, los segundos van a ser los segundos que brinde aquí. Y esto podemos comentar para que podamos referirlo en un segundo. Y otra vez aquí podemos simplemente cambiar esto para que sean nuestros trabajadores actuales, que va a incluir cada una de las instancias que tenemos aquí. Y entonces solo vamos a llamar a dot join de nuevo aquí. Está bien, así que sigamos adelante y ejecutemos esto. Entonces. Reconoceré que AMI, deberíamos estar haciendo exactamente lo mismo. Y parece que nos encontramos con un problema aquí. Entonces veamos dónde está el problema en nuestros métodos de unión aquí para decir que no podemos unirnos a una amenaza antes de que comenzara. Por lo que probablemente se olvidó de iniciar el hilo interno aquí porque ya no lo llamamos aquí. Entonces sigamos adelante y probemos eso una vez más. Está bien, Ahí vamos. Entonces tenemos nuestra salida de ejecución aquí, y tenemos nuestro sueño, que actualmente es sólo tres segundos desde siempre. Todavía tenemos esta sintaxis aquí, el menos dos. Entonces podemos ver aquí solo estábamos, ya sabes, en este caso fue bastante sencillo. Nos limitamos a tomar sus dos funciones aquí y poner cada una de estas en una clase separada, que por supuesto para este caso no tiene tanto sentido. Pero si estás haciendo cosas complejas como, ya sabes, quieres escribir valores específicos en una base de datos. Y parte de ese proceso está estructurando todos los valores y formateándolos para que estén en la estructura correcta y luego subiéndolos a la base de datos. Entonces si tienes un trabajador de base de datos específico solo puedes poner en los valores brutos y solo estructurará los datos por ti. Y luego realizaremos la carga. Y todo eso está algo oculto a nuestra función principal se cuida dentro de cada clase misma. Y por supuesto aquí seguimos llamando al punto se une en cada uno de estos solo para especie de bloquear la ejecución. Ahora, podemos ver aquí o no podemos construir. Ya veremos en un segundo. Recuerda que teníamos estos parámetros Dan y aún podemos hacer lo mismo porque estamos pasando los argumentos de palabra clave. Podemos hacer realidad a Damon aquí. Y luego porque nuestro trabajador soñoliento acepta todos estos argumentos de palabras clave y los pasa, va a tomar esto porque es un argumento de palabra clave o encontrar un valor específico, va a tomar esto y pasarlo al padre clases, que en este caso es solo el hilo. Entonces se va a establecer el parámetro daemon en true, que por supuesto podemos ver lo efectivo si eliminamos el join Call aquí. Entonces sigamos adelante y solo ejecutemos esto una vez más solo para especie de ver el efecto de agregar ese parámetro de argumentos de palabra clave en la parte superior aquí. Entonces se puede ver aquí el parámetro de estambre fue luego pasado al padre porque ya no estamos llamando al método join, obtenemos exactamente lo mismo que vimos en la lección anterior. Ahora otra cosa que también podríamos hacer es si quisiéramos sólo tener todas estas clases siempre sean demonios. También podemos establecer aquí el parámetro daemon, que tendrá el mismo efecto. Excepto por supuesto en este caso la lógica nos está escondida, cual puede no ser lo mejor, y realmente no tenemos mucho control sobre ella a menos que sepamos específicamente lo que buscamos y actualicemos el atributo de la clase sí mismo. Pero en realidad algo importante a saber es que el parámetro daemon necesita establecerse antes de llamar al método start. Entonces porque también estamos llamando a empezar aquí, si tomamos a nuestro trabajador y configuramos a Daymond para que sea falso, no va a funcionar porque el parámetro húmedo necesita ser ajustado antes de iniciar el hilo, lo cual veremos en un segundo aquí. Entonces, sí, ahí vamos. Obtenemos el error por esto. Entonces por supuesto, ya sabes, esconder esto no es lo mejor y es mejor si quisiéramos hacer esto, pasarlo con la opción de argumento de palabra clave que tenemos aquí. Y en este caso, sólo lo estamos haciendo un poco más limpio porque estas funciones, primer lugar, ya no están aquí, sino que hay métodos de la propia clase. Y, ya sabes, toda esa lógica es algo que pasa a cada uno de los diferentes trabajadores entre comillas que tenemos aquí, todos hacen su propio trabajo separado, responsables de una cosa separada o específica. Y así solo decimos, está bien, vamos a correr, este trabajador va a hacer esto. Y no llamamos al join al final aquí. Nosotros los vamos a dirigir trabajador. Se va a hacer una cosa específica. Y realmente el programa principal es solo para la orden de ejecución y lógica general. tanto que a todos les gustan las cosas de procesamiento grande. No necesitamos desorden este archivo y hacerlo muy grande. Podemos poner cada uno de estos en archivos separados o en clases separadas aquí. Y entonces, ya sabes, si necesitamos mirar la lógica específica, entonces todo estará contenido dentro de este único expediente. Cualquier tipo de relevante para la ejecución de cada una de estas clases. 5. Crea un lector de Wikipedia: Muy bien, entonces ahora que hemos creado como los fundamentos de tener nuestras clases de subprocesos. Sigamos adelante y saltemos al proyecto real que queremos estar haciendo para especie de implementar este enhebrado y de una manera más útil. Entonces lo que vamos a hacer es llevarnos aquí la lista de empresas S y P 500 de esta página. Y sólo vamos a desplazarse por todos estos símbolos. Y luego por cada símbolo que tenemos aquí, sólo vamos a visitar la página correspondiente de Yahoo Finanzas. Y sólo vamos a extraer este precio actual aquí mismo. Y luego vamos a guardar esas cosas en una base de datos. Y así el proceso que tenemos aquí es básicamente tenemos tres cosas pasando que pueden funcionar de forma independiente. Y va a haber un montón de cosas de la red que realmente no queremos que nos bloqueen. Entonces lo primero que podemos hacer es simplemente agarrar la lista de empresas desde aquí. Y realmente lo que eso conlleva es sólo una petición a aquí. Y luego simplemente desplazándose por esta mesa y siempre solo sacando la primera entrada. Una vez que tengamos cada una de estas entradas, podemos entonces hacer una solicitud aquí al sitio y sacar este valor. Entonces eso es solo una solicitud de red ahí esperando este valor, tipo de extraerlo. Y una vez que tengamos ese valor, podemos insertarlo en la base de datos. Entonces podemos ver que esta probablemente sería una aplicación realmente agradable para enhebrar si queremos hacer esto lo más rápido posible, porque hay un montón de cosas de red pasando, ya sabes, cargando páginas esperándolo, insertando en la base de datos, a la espera de la confirmación. Y en realidad no hay muchas tareas de CPU pasando. Entonces, sí, Para hacer esto, sólo vamos a empezar escribiendo la clase que nos permita extraer las entradas de aquí. Entonces en nuestros trabajadores, voy a crear aquí un nuevo trabajador. Y lo llamaremos trabajador Wiki. Y para esto, vamos a estar usando la biblioteca de peticiones para realmente hacer las solicitudes. Y también vamos a estar usando Beautiful Soup. Si no estás familiarizado con Beautiful Soup o si lo has olvidado y asegúrate volver a consultar la clase de desguace web. Pero por lo demás, la biblioteca es bastante directa. Así que sólo un poco de pasar por aquí. Debe ser relativamente sencillo de tipo de seguir adelante. Vamos a tener nuestra clase de trabajador wiki aquí. Y vamos a tener nuestro método de inicialización. Y realmente lo que podemos hacer aquí es por ahora, solo podemos codificar duro esto para que sea URL de la que queremos fregar. Simplemente copiaré eso. Y realmente cuando creemos nuestra clase, Vamos a todo lo que vamos a estar haciendo es sólo vamos a tener su yuan o L, El, ya sabes, este atributo de clase. Entonces lo siguiente que vamos a hacer es que vamos a crear un método de clase que va a ser conseguir empresas S y P 500. Y lo que esto va a hacer es que va demasiado bien. Al igual que el método implica, va a conseguir los de la empresa para nosotros. Entonces vamos a hacer una petición. Vamos a utilizar la biblioteca de solicitudes, hacer una solicitud GET a nuestra URL aquí, así. Y sólo vamos a asumir que todo está pasando, pero sólo podemos tener aquí y como si nuestro código de estado no es a un 100 y voy a devolver una lista vacía y tal vez podamos imprimir como no pude conseguir. Y árboles, ya sabes, lo que sea. Esto es sólo una especie de básico. Por supuesto que puedes extender esto a todos los diferentes códigos de estado que te interesen o incluso hacer algo de registro aquí, pero solo tendremos esto para el mínimo desnudo. Y entonces vamos a usar, lugar de tener todo en el mismo método, vamos a seguir adelante y crear un segundo método que realmente va a extraer símbolos de empresa. Y esto va a tomar en la página HTML. Y este método aquí va a ser lo que realmente va a ser responsable de sacar cada uno de estos símbolos. Entonces sigamos adelante y veamos la fuente de la página, que puedes hacer haciendo clic derecho aquí y ver fuente de la página o Comando Alt J. Y estamos buscando, Vamos a seguir adelante y a entender la estructura. Entonces busquemos el primer símbolo aquí, que sólo va a ser m Y si tipo de colapsamos esto hacia abajo, esta es la mesa que estamos buscando. Y esta mesa en realidad bastante agradable como podemos ver. Por lo que hay una idea asociada a esta mesa. Y si solo buscamos esto, entonces podemos ver que esta es la única identificación a esta mesa. Entonces no hay Mirar a nosotros ni nada así tampoco, lo cual es muy bonito. Entonces sí, sigamos adelante y creemos nuestros hermosos bucles. Hermosa instancia de sopa, que va a tomar la página HTML. Y vamos a usar la L x. Voy a analizar. Nosotros sólo vamos a poner esto aquí porque nota si no ponemos esto aquí, sólo vamos a recibir una advertencia o ni siquiera una advertencia, igual que una notificación. Podemos dejarlo fuera por un segundo sólo para ver. Pero sí, solo especificando esto para que no consigamos ese registro, lo cual puede ser un poco molesto. De acuerdo, entonces lo siguiente que tenemos que hacer es que primero tenemos que encontrar esta tabla de contenido, y luego vamos a recorrer esta tabla. Por lo que nuestro contenido o nuestra mesa va a ser sopa punto hallazgo. Y vamos a encontrar por el id, que van a ser los constituyentes. Y solo voy a repasar esto un poco más rápido ya que esto como más de como cosa raspado web, no necesariamente enfocada en el threading, sino solo para que tengamos un trabajador disponible para nosotros que pueda realmente obtener estos contenidos para que podamos seguir usándolos. Entonces esta es nuestra mesa. Y ahora que tenemos nuestra mesa, queremos repasar todas las filas. Por lo que nuestras filas de tabla. Si entramos en nuestra mesa, aquí vamos a encontrar todas las etiquetas de fila de tabla en nuestra tabla. Entonces podemos ver que hay uno en el encabezado, y luego hay por cada fila, tenemos uno aquí en el cuerpo. Y luego podemos recorrer nuestras filas de tabla. Entonces podemos decir para fila de tabla en filas de una tabla y vamos a omitir la primera. Porque notarás si nos estás probando que el primero realmente está en el encabezado aquí. Y así por supuesto, ya sabes, no hay ningún símbolo que extraer aquí, así que vamos a saltarnos el primero. Y luego por cada fila de tabla, vamos a extraer el símbolo, que va a ser, vamos a encontrar la primera etiqueta T d, que podemos ver aquí. Y desde aquí vamos a sacar el texto. Y también vamos a quitar al personaje de nueva línea al final aquí. Entonces estos van a ser nuestros símbolos. Y ahora o bien podemos recoger a estos mentalistas y luego devolver toda la lista. O también podemos usar un generador y simplemente sentir o símbolo. Y luego desde aquí podemos decir yield from dot, extraer símbolos de empresa. Y sólo necesitaré pasar la página HTML DOM, que va a ser sólo la parte de texto de nuestra respuesta aquí. De acuerdo, así que una cosa a notar en realidad es que no estamos usando una propiedad de clase aquí. Y así lo que podemos hacer es que realmente podemos hacer de esto un método estático al que pertenece, básicamente se comparte a través de todas las instancias de la clase. Y entonces no lo hacemos, porque no estamos usando ninguna propiedad de clase es en sí misma. Está bien. Entonces este va a ser nuestro trabajador Vicki. Pero claro, Sigamos adelante y probemos esto. Ahora porque estamos usando Beautiful Soup. De verdad. En este punto se vuelve, habrá, ser un poco más agradable si queremos reutilizar esto más adelante. Solo para asegurarnos de que todo nuestro entorno, todas nuestras bibliotecas y cosas sean algo así como contenidas. Vamos a crear un entorno virtual. Entonces voy a ir pitón menos m, Entonces, entonces alguien para crear un entorno virtual. Y el directorio actual que se va a llamar Ben. Hit Enter, que va a crear nuestro entorno virtual para nosotros. Y esto simplemente básicamente nos da una especie de nueva instalación de Python que podemos usar, que es justo si lo activamos, se vuelve un poco más agradable porque entonces estamos un poco conscientes de qué bibliotecas estamos usando y podemos hacer un requisitos específicos para que todo sea tipo de autónomo y no dependa de nuestra configuración actual del sistema. Entonces vamos a seguir adelante y activar nuestro entorno virtual. Y si solo entramos en Python, por ejemplo, ahora puedes ver dónde en nuestro entorno virtual y trato de importar esta clase, realidad estamos recibiendo un problema porque en este momento no tenemos hermosa supertormenta. Entonces vamos a decir de los trabajadores dot wiki, worker, vamos a importar el trabajador clave 0 e incluso la solicitud no está instalada. Entonces vamos a seguir adelante y hacer solicitudes de instalación de pip. Y debido a que estamos en nuestro entorno virtual, realidad va a usar la versión pip de nuestro entorno virtual. Por lo que puedes ver aquí el PIP para entorno virtual aquí. Y luego lo siguiente que queremos hacer es también querer instalar Beautiful Soup. Entonces para ello, vamos a teclear en pip, instalar el OH, a sopa completa para. Aquí no hay tipo. Está bien, genial. Y sí, estas son las dos bibliotecas que no deberíamos necesitar. Entonces podemos seguir adelante y probar eso. Una vez más y genial. Ahí vamos. Funciona. Podemos probar esto en un segundo. Pero solo escribamos también nuestros paquetes actuales en un archivo de requisitos para que si es necesario, podamos recrear esto más adelante. De acuerdo, así que sigamos adelante y probemos este wiki y trabajador. Y vamos a hacer una instancia de n. y luego podemos decir por símbolo en McKee, punto trabajador consigue empresas S y P 500, solo llamando a nuestro método de clase aquí. Vamos a seguir adelante, imprimimos un símbolo, y luego vamos a interrumpirla. Generación a partir de un tipográfico aquí. Está bien. Vamos a imprimir el símbolo y luego vamos a romper. Y sí, aquí vamos. Entonces esto es sin embargo, una advertencia de que estábamos recibiendo ese tipo de como elegir un 12 específico. Por eso solo puedes poner L, x y L ahí dentro. Simplemente deja que no los haga. ¿ Todo bien? De acuerdo, Así que mirando nuestro sencillo, está bien, así que tenemos el primero. Y entonces sólo tengamos una lista de símbolos. Y hagamos lo mismo. Pero adjuntemos cada símbolo a nuestra sencilla lista para asegurarnos de que no estamos recibiendo nada extra, ya sabes, al final o algo así. Y luego vamos a ver la longitud de nuestro simbolizado, que tiene 505, que en realidad es el número de empresas en esto. Sé que es un poco confuso porque dice 500 y en realidad es 505. Pero eso es genial porque eso es exactamente lo que esperábamos. Y dos, ningún extra confirman esos. Podemos mirar al último. Desplazarse todo el camino hacia abajo. Una vez demasiado lejos. Ahí vamos. Está bien, Perfecto. Por lo que ahora tenemos nuestra clase para conseguir los símbolos. Ahora de nuevo, pasamos por esto un poco más rápido sólo porque de nuevo, queremos asegurarnos de que nos enfoquemos en enhebrar aquí y no ir específicamente por construir policías del oeste. Entonces, sí, si estás familiarizado con Beautiful Soup y toallitas de cultivo, genial. Y si no lo estás, probablemente habrías podido seguir de todos modos, ya que nuestra sintaxis es bastante sencilla aquí y solo estamos pasando por diferentes elementos HTML. Pero si quieres un refresco sobre eso, si quieres aprender esta mezcla, adelante y simplemente agita nuevamente la clase de desguace web. Pero sí, así que ahora tenemos nuestro trabajo wiki están disponibles para nosotros, que va a ser lo primero por supuesto que necesitamos. Lo cual básicamente nos va a ver con todos nuestros valores que luego podemos usar para, ya sabes, más adelante, buscar a las empresas individuales por tipo de manipular aquí esta URL. Y entonces también podemos seguir adelante y una vez que extraigamos este valor aquí, entonces podemos seguir adelante y enviar eso a una base de datos. Entonces detengámonos aquí por ahora y luego sigamos con eso en la siguiente lección. 6. Crea un lector de Yahoo Finanzas: Muy bien, entonces ahora que tenemos nuestra configuración de trabajador wiki, sigamos adelante y escribamos la clase, que va a ser una clase de subprocesos, que va a extraer el precio de usar esta URL de Yahoo Finance aquí. Está bien, así que también voy a borrar a estos dos trabajadores de aquí porque, bueno, ya no los necesitamos. Entonces sigamos adelante y eliminemos estos realmente rápido. Aquí vamos a crear un nuevo trabajador, que va a ser Biao que financie precio. Llamaremos a esto trabajadores de Yahoo Finanzas. Y luego aquí dentro vamos a importar primero el subproceso porque lo estamos usando. Pero entonces tendrá un trabajador de precio de yahoo Finance, que va a heredar del hilo de punto de enhebrar, como lo hicimos antes. Y luego en nuestro método de inicialización, sólo vamos a asegurarnos de inicializar eso a. Y también vamos a aceptar argumentos de palabras clave que vamos a pasar aquí a nuestras clases de padres. De acuerdo, así que esto es lo que teníamos antes. Ahora solo asegurémonos de iniciar el hilo para que sepas que llegaremos a ese punto. Y luego también vamos a tener el, vamos a sobrescribir el método de ejecución, pero definirlo en un poco. ¿De acuerdo? Entonces, ¿qué necesitamos? Bueno, también necesitamos aceptar el símbolo que queremos tener. Tipo de querer guardar ese símbolo como un atributo de clase. Y entonces también necesitamos la URL base que queremos usar, que básicamente va a ser todo excepto esta última parte. Por lo que esta va a ser nuestra URL base. Y luego al final aquí, podemos, bueno, en realidad, podemos tener nuestro año base recién definido aquí. Y luego vamos a establecer la URL real para que sea nuestra URL base. Y usemos cadenas formateadas aquí. Y entonces sólo vamos a sumar el símbolo al final aquí. Entonces sí, sólo vamos a tener nuestro año base. Yo seré la primera parte aquí mismo. Y luego por aquí, vamos a sumar en ella son similares al final. Y así realmente esto aquí sólo nos va a dar cualquiera que sea el símbolo. Simplemente nos va a dar básicamente el mismo resultado que este. Es sólo una manera más ordenada en mi opinión de expresar esto. De acuerdo, entonces ahora tenemos a nuestro trabajador aquí, y ahora queremos sobrescribir el método de ejecución, que es básicamente lo que tenemos que hacer aquí está bien, Así que ahora tenemos este urinario. Entonces, uh, una vez más, necesitamos extraer este precio aquí. Entonces vamos a entrar en el HTML y tratemos de encontrar esto. Entonces lo tenemos aquí encendido, en realidad está en el título. Eso es muy conveniente. Entonces vamos a ver si está en otro lugar también, pero ya podríamos conseguirlo a partir de ahí. También está aquí. Y vamos a ver si está bien. Por lo que también regresó en guión en algún lugar. Por lo que hay diferentes formas en las que podemos ir para hacer esto. Una de ellas es por supuesto, podemos extraerla. ¿ Dónde fue eso? ¿ De? Donde aparece como podemos extraer de aquí. Pero si hacemos clic derecho y copiamos el XPath, y solo sigamos adelante y echemos un vistazo a esto. Sí, así que no parece particularmente limpio. No hay como identificación específica ni nada que podamos usar aquí. Y debido a que también está incluido en el título, no podemos simplemente extraerlo de ahí. Esto es por supuesto, un poco dependiente es asumiendo que Yahoo tipo de mantener este formato. Pero, ya sabes, si, si lo cambian, como si cambiaran también este formato aquí arriba, también vamos por supuesto que vamos a tener que adaptar nuestro rasguño o de todos modos. Entonces, solo vayamos con la opción más simple por ahora. Sólo vamos a estar extrayéndolo del título en sí aquí. Está bien. Por lo que de nuevo, vamos a importar desde la carpeta BS. Vamos a importar Y Hermosa Sopa. Y sigamos adelante y solo probemos esto o noticias sin embargo. También necesitamos importar el módulo de solicitudes. Y solo sigamos adelante y usemos esto para las pruebas. Por lo que vamos a ir establece nuestra URL aquí. Vamos a importar solicitudes, diremos, de acuerdo, igual solicita punto obtener nuestra URL. Y luego vamos a tener que nuestra sopa sea una instancia de Beautiful Soup, tomando en el texto de nuestras peticiones. Entonces tengo un error tipográfico aquí. Yo no era importante, importante. Vuelve a intentarlo. Vamos a ir al título de punto de sopa, que en realidad directamente nos deja acceder a eso, ¿verdad? Entonces afortunadamente lo hace, parece que este contenido se genera dinámicamente, pero eso está bien. Off to ir sobre esto de una manera diferente. Vamos a utilizar la biblioteca L XML en su lugar. Y realmente solo lo vamos a usar para algo muy sencillo, lo cual solo va a estar asegurándose de que podamos usar XPath ya que actualmente no está soportado con Beautiful Soup. Entonces vamos a decir desde x, soy L, x y L, y vamos a importar HTML. Entonces yo sí, claro que no lo tenemos instalado. Entonces sigamos adelante e instalemos rápidamente puesto L x L. Ahí vamos. Voy a escribir esto a unos requisitos. Vuelve a poner nuestro Python, intentemos importar eso. Ahí vamos. Y tomemos, ya no necesites bella superior. Sigamos adelante y tengamos nuestro ustedes estamos vamos a ir a mandar una solicitud y sondear solicitudes. Está bien. Y entonces vamos a decir, bueno, contenido de nuestra página que podemos llamarla va a ser HTML desde string. Por lo que sólo vamos a importar HTML aquí desde L XML. Esto sólo nos va a ayudar a analizar usando XPath. Estoy de nuevo, notarás que la sintaxis es muy sencilla, así que no hay necesidad de estar familiarizado con esta biblioteca. Simplemente vamos a usar básicamente estos dos métodos a partir de él. En primer lugar, vamos a poner aquí la cadena HTML, que se va a guardar aquí. Y entonces esto tiene un método ex-pat x path que vamos a usar. Y entonces lo que tenemos que hacer aquí es ahora tenemos que conseguir el XPath para esto, lo cual podemos hacer muy fácilmente con solo hacer clic derecho en Copiar XPath. Entonces una vez que encontremos este elemento aquí, que solo podemos hacer buscando así, puedes hacer clic con el botón derecho en Copiar XPath, y luego seguir adelante y poner eso aquí. Y ahí vamos. Entonces podemos ver si podemos acceder al primer elemento, al texto, entonces vamos a poder extraer el valor aquí así. Está bien, así que sigamos adelante y pongamos en práctica. Por lo que hemos probado esto para asegurarnos de que tenemos algo que está funcionando. Entonces sigamos adelante y hagamos eso de nuevo. Vamos a tener nuestro pozo, en realidad podemos simplemente copiar eso, así que como ya lo hicimos. Entonces primero vamos a emitir nuestra solicitud, que va a ser a través de esto. Y entonces tenemos contenidos de nuestra página como este. Y entonces queremos tener un precio como este. Y no estamos haciendo mucho manejo de errores aquí. Por ejemplo, ¿qué pasa si aquí no obtenemos respuesta? Este valor no se puede convertir en un flotador o lo que sea. Entonces por supuesto, ya sabes, si quieres hacer esto más robusto, puedes agregar código de estado checando aquí como lo hicimos en nuestro trabajador wiki. Puede agregar sentencias try-except para manejar diferentes casos en los que puede que no siempre esté sacando un valor flotador. Pero sólo para un poco para mantener esto simple, sólo vamos a mantenerlo así sin hacer demasiado manejo de errores. Entonces ahora tenemos nuestro precio, y entonces solo podemos seguir adelante e imprimir nuestro precio por ahora. De acuerdo, así que volvamos a nuestra función principal aquí. Y ahora vamos a cambiar esto un poco e importar a nuestros dos trabajadores y sólo que trabajen juntos un poco. Por lo que aquí queremos importar al trabajador de precios de Yahoo Finance. Entonces lo primero que vamos a hacer es crear una instancia de nuestro trabajador wiki. Y vamos a decir por símbolo en trabajador Wiki, no consigas empresas S y P 500. Esto sólo nos va a dar un símbolo a la vez. Y ahora vamos a crear una instancia del trabajador de precios de Yahoo Finance. Y el símbolo que vamos a pasar aquí sólo va a ser directamente el símbolo que tenemos aquí. Y luego si queremos y mantenemos una lista de nuestros trabajadores actuales, como hicimos formarnos. Escrito son Yahoo Finanzas, trabajador de precios. Y luego solo usa aquí el método join. Y saca esto. Todavía podemos hacer tiempo de distracción. Tomó y renombró nuestra variable aquí para desechar el tiempo de reinicio. Muy bien, entonces necesitamos asegurarnos de que usamos la instancia de su trabajadora wiki aquí, no solo la definición de costo en sí. Entonces repasemos lo que hicimos. Y básicamente nosotros tipo de, estamos aplicando lo que aprendimos para enhebrar aquí ahora usando nuestros dos trabajadores. Entonces el primero que tenemos es nuestro trabajador wiki, que de nuevo, si lo repasamos, tiene el método principal que vamos a usar aquí, que va a conseguir que las empresas S y P 500, que sólo va a mandar este solicitud. Y para esta solicitud de los elementos de la tabla, Es esto, sólo voy a extraer el primer elemento, que suponemos que va a ser el símbolo. Y que vamos a utilizar como entrada lejos Yahoo Finance precio trabajador. Y para esto, entonces vamos a enviar una solicitud a esta URL. Vamos a extraer del HTML usando esta clase XML HTML aquí. Simplemente vamos a usar esto para que realmente podamos obtener el tipo XPath de tener esto sea una manera fácil de obtener el XPath un extracto el precio de aquí y convertirlo en un flotador. Entonces vamos a estar desplazando por encima de estas listas de empresas que tenemos aquí. Y por cada símbolo que obtenemos, entonces vamos a crear un hilo, que va a crear esta solicitud. Y entonces solo lo va a imprimir a la salida por ahora. Entonces estamos rastreando el tiempo de ejecución tal como lo hicimos antes. Y aquí estamos llamando a unirse al final, solo para que básicamente todo quede bloqueado hasta que cada hilo termine. Y ni siquiera necesitamos hacer nada más aquí porque tiene el, estamos anulando el método Run predeterminado, que sucede justo después de iniciar el trabajador. Entonces, sí, antes de correr eso, quiero implementar una cosa más que solo va a estar desacelerando nuestro perimetral. Vamos a importar tiempo y vamos a importar aleatorio sólo para que no hagamos spam. Vamos a decir Time dot sleep. Vamos a decir 200 puntos aleatorios al azar. Entonces eso significa que cada hilo va a dormir entre 0 a 20 segundos ya que esto genera un número aleatorio entre 01. Entonces eso va a ralentizar las cosas sólo un poquito y va a hacer que nuestro programa funcione. Bueno, supongo que en este punto, como un máximo de 20 segundos de algo no duerme como 20 segundos. Podemos incluso empujar esto hasta 30 solo para, ya sabes, como no spam Yahoo mientras estamos haciendo esto. Porque vamos a cambiar las cosas un poco más tarde para no gustar engendrar un trabajador individual por cada símbolo que tenemos aquí. Pero sí, y en realidad sí quiero implementar aquí un cheque extra, que va a ser si nuestro código de estado es 200. Entonces por ahora, vamos sólo, vamos a parar. Y, ya sabes, detener la ejecución para que no lleguemos como span con mensajes de error y esas cosas. Entonces sigamos adelante y ejecutemos nuestra función principal. Lo voy a hacer sobre la terminal esta vez porque tengo mi configuración de entorno virtual aquí, cual tiene todo instalado que necesito. Entonces sigamos adelante y ejecutemos esto. Y después de esperar un poco, Ahí vamos. Por lo que tenemos los precios empezando a entrar aquí. Algunos nos interrumpen. Pero sí, todo está funcionando como se pretendía. Ahora bien, te puedo garantizar que aquí probablemente haya algunos errores que no estamos captando, lo cual puede deberse a una variedad de razones con las que deberíamos estar tratando mejor. Pero por ahora sólo vamos a dejar esto como está por ahora. Deberíamos por lo menos ser como cerrar sesión esto o algo así. Pero lo que sea por ahora, dejémoslo tal como está, ya que el propósito principal de esto era solo configurar los hilos para realmente hacer las solicitudes separadas. Entonces esos son los hilos separados. Para que podamos hacer todas estas solicitudes separadas para que podamos, ya sabes, no estemos bloqueados por todo este tiempo de red. Pero en el futuro, en realidad vamos a ver cómo podemos tipo de límite y escala y tipo de definir cuántos trabajadores queremos tener para que cada uno tenga todo esto un poco más estructurado en lugar de solo desove y hilo individual para cada iteración que tenemos aquí. Y esto en realidad también nos va a enseñar cómo podemos pasar información entre diferentes hilos para que todo esto pueda estar funcionando de forma concurrente. Llegaremos a eso en el siguiente video. 7. Queues y programar un programador magistral: Muy bien, Así que en la última lección, como que configuramos a nuestro trabajador de Yahoo Finanzas así como a nuestro trabajador wiki, que teníamos antes. Y simplemente nos desplazamos por todos los símbolos y enviamos solicitudes y, ya sabes, conseguimos los precios que pudiéramos. Pero ahora vamos a sistematizar esto y hacerlo un poco más agradable. Y lo que vamos a hacer es que estos sean procesos separados. Entonces en lugar de desplazarse por el símbolo y luego por cada símbolo creando directamente un hilo, lo que vamos a hacer es separar todas estas entidades. Entonces vamos a recorrer primero todos los símbolos. Y luego sólo vamos a, cada vez que tengamos un símbolo, sólo lo vamos a poner en algo llamado cola. Y luego tendremos diferentes hilos de los trabajadores de Yahoo Finance los cuales van a estar leyendo desde esa cola. Por lo que como que tenemos esta cosa intermedia. Y así sí, de nuevo, esa cosa que vamos a estar usando se llama cola. Y realmente la idea, él, idea aquí es que podemos tomar elementos y podemos ponerlos en la Q. Y así de esa manera, estamos como separando rápido o lo lento que se están ejecutando los diferentes hilos. Porque la Q se puede acumular y podemos poner muchos elementos en. Y entonces nuestros trabajadores pueden, nuestro trabajador aguas abajo. Por lo que los que están tomando de esa cola sólo pueden leer de la cola cuando estén listos. Entonces de esa manera, también tenemos un poco de, y lo veremos en un futuro. Tenemos más control sobre, ya sabes, cuántos trabajadores de entrada quisiéramos tener si podemos escalar eso. Pero también cuántos como lectores de la cola, cuántos consumidores de la cola queremos tener. Si notamos que nuestra cola se está apilando demasiado rápido y apenas está creciendo, entonces podemos sumar más consumidores. Y si notamos que nuestra cosa o la q siempre está vacía básicamente, entonces realmente podemos reducir el número de consumidores porque realmente no nos está brindando ningún beneficio tener tantos trabajadores. Muy bien, así que para implementar una cola, vamos a usar la biblioteca de multiprocesamiento. Y desde aquí vamos a importar Q, esto. Y luego vamos a crear una cola, que va a ser nuestro símbolo Q, que va a ser una instancia de Q como esta. Y entonces lo que vamos a hacer es solo comentemos esto por ahora. Comente esto aquí afuera. medida que fregamos los símbolos aquí, sólo vamos a usar nuestro símbolo q. Y aquí vamos a poner el símbolo, así que vamos a insertarlo en la cola. Ahora las señales son seguras para subprocesos, lo cual es genial porque eso significa que en realidad podemos usar el sistema fiscal de subprocesos. Está bien, y así, sí, eso es todo lo que tenemos que hacer de esta manera. Ponemos elementos en nuestra cola. Y así si solo ejecutamos esto y entonces solo podemos imprimir la cola al final. Y en realidad hay un método get que podemos usar el cual solo obtiene el siguiente elemento de la cola. Por lo que podemos ejecutar nuestra función principal solo para especie de ver los resultados de esto. Entonces vemos que tenemos una cola implementada o una instancia del objeto aquí. Y usando el método get, obtenemos el primer valor de la cola, que en este caso es el primer símbolo. Nosotros lo esperamos. De acuerdo, entonces ahora que estamos poniendo estos elementos en la cola, ahora podemos tener una corriente separada de procesos que pueden estar consumiendo de esta cola. Y eso es lo que nuestros trabajadores del premio Yahoo Finance van a ser esencialmente. Pero también vamos a cambiar las cosas aquí arriba un poco. Y en lugar de que los trabajadores del precio de Yahoo Finance hagan esto directamente, en realidad vamos a cambiar esto y vamos a tener un programador que se va a hacer cargo del subproceso. Y luego vamos a tener a nuestro trabajador de precios de Yahoo Finance en sí solo ser la clase que extrae la información de precios. Pero tendrá una clase diferente Kino responsable de la parte de multiprocesamiento. Por lo que llamaremos a este el programador de precios de Yahoo Finance. Y esto va a ser una instancia de correr. Y esto en realidad ya no va a ser una subclase de la clase de subprocesos. Entonces aquí otra vez, vamos a inicializar esto. Vamos a inicializar la clase padre. También vamos a permitir argumentos de palabras clave. Ups, y pasen esos a la clase de padres aquí. De acuerdo, y luego vamos a anular el método de ejecución. Y aquí sólo vamos a tener un bucle infinito. Y básicamente lo que vamos a hacer en este bucle infinito es lo que sólo vamos a leer de la cola. Y así lo que necesitamos aquí también es que necesitamos una cola de entrada porque necesitamos una lectura de una cola. Entonces vamos a proporcionar que como argumento de entrada aquí tiene un argumento de inicialización. Vamos a tener nuestra cola de entrada aquí. Y luego vamos a tener nuestro siguiente valor solo ser cola de entrada autodidacta. Otra vez. Ahora se trata de una operación de bloqueo, lo que significa que va a bloquear esto, o esta operación va a bloquear hasta que realmente nos devuelva un valor. Llegaremos a esto más tarde. Pero básicamente, mientras este bucle se está ejecutando, solo va a intentar seguir leyendo desde la cola. Y cada vez que obtiene un valor, entonces va a continuar la ejecución. Entonces también lo que queremos hacer aquí es porque tenemos un bucle infinito aquí en algún momento queremos salir de él. Entonces una manera fácil de hacer esto para decir, está bien, si enviamos el valor w1 y terminamos, ahora solo queremos salir. Aparte de eso. Si sí obtenemos un valor y este valor no se hace, vamos a suponer que es un símbolo. Y entonces lo que queremos hacer es que queremos tener una instancia de nuestro trabajador de precios de Yahoo Finance. Y el símbolo que vamos a pasar aquí va a ser nuestro valor porque vamos a asegurarnos de que nuestra Q upstream realmente ponga el valor aquí dentro. Y luego también vamos a cambiar este método de ejecución. Y en su lugar vamos a renombrarlo para extraer u obtener precio por Spark. Simplemente lo llamaremos buen precio. ¿ Está bien? Entonces vamos a llamar a esto, y vamos a decir precio. Y aquí, en lugar de imprimir el precio fuera, Vamos a seguir adelante y devolver el precio. Entonces vamos a decir que nuestro precio es igual a usar la instancia de nuestro trabajador de Yahoo Finance aquí, vamos a conseguir el precio y en realidad necesitamos mover esto aquí arriba, iniciar el hilo. Y luego F queremos aquí podemos tipo de imprimir la prensa por ahora y más adelante, en realidad vamos a poner esto en una cola diferente, que va a ser responsable, que trabajador downstream allá va a ser responsable de insertar en la base de datos. Pero por ahora, sólo vamos a imprimirlo. Y Yang, ya no necesitamos el sueño aquí. Pero lo que podemos hacer si queremos hacer es agregar un poco de sueño al final aquí, ya que en realidad no lo estamos, esto no es como una solicitud API, por lo que no estamos obteniendo información de la API en el encabezado es como grandes límites o algo así y cuántas solicitudes podemos hacer. Entonces para ser un poco respetuosos después de cada solicitud, solo vamos a dormir en cualquier lugar entre 01 segundos solo para ralentizar un poco el proceso. Entonces de nuevo, lo que tenemos aquí es que ahora tenemos nuestra clase de programador, que tenemos un poco Moverse para ser nuestra clase de subprocesos maestros. Y esto va a tomar una cola de entrada como entrada. Y luego vamos a empezar el hilo. Y entonces básicamente va a entrar en un bucle infinito. Se va a seguir leyendo desde la cola hasta que lea el valor, momento en que va a estallar. Y cada vez que obtiene el valor y este valor no se hace. Se va a crear una instancia de la clase de trabajador de precio de Yahoo Finance. Va a proporcionar este valor como símbolo. Desde consulta o asumiendo que eso es lo que estamos obteniendo de esta clase aquí. Y entonces nuestros jóvenes trabajadores del precio de las finanzas sólo van a ser los responsables de extraer el precio ahí. Y sí, eso es todo por ahora. Entonces sigamos adelante y tomemos esto por aquí. Y vamos a crear una instancia de antemano para que, ya sabes, en cuanto empecemos a poner valores hasta la cola, realmente podamos empezar a consumirla. De acuerdo, así que crea aquí una instancia de nuestro horario de precios de Yahoo Finance. No, hay que asegurarse de que damos la cola de entrada. Ahora la cola de entrada que vamos a utilizar va a ser el símbolo Q, ya que aquí es de donde debería estar leyendo. Entonces, sí, ahora mismo sólo tenemos un hilo que estamos creando aquí. Solo vamos a crear una lista para esto en caso de que quieras tener más, que luego lo haremos en finanzas, precio, programador, rentas. Y así. Y entonces podemos simplemente mantener este bucle aquí, ya no necesitamos esto. Muy bien, entonces una cosa que tenemos que hacer al final aquí es porque estamos esperando el valor w1. Una vez que hayamos terminado, asegúrate de que ponemos aquí hecho. Para que nuestra clase realmente va a salir, o ese hilo es en realidad una salida. Una cosa por supuesto que podemos hacer en lugar simplemente poner una es si queremos cambiar esto más adelante, lo cual vamos a decir muy pronto, vamos a decir para bucles. Por cuantos hilos tengamos, vamos a poner un valor w1 para asegurarnos que cada instancia de nuestro hilo en realidad se va a romper. Porque si solo ponemos un valor aquí, porque estamos consumiendo de esta cola, cada, cada hilo solo va a estar leyendo un valor. Y una vez que llegue a ese valor a básicamente hecho. Entonces, entonces si tenemos múltiples hilos y solo uno de ellos ve el valor w1, entonces digamos que tenemos cuatro hilos. Una de ellas lecturas hechas que los otros tres hilos no se van a estar rompiendo porque la cola está vacía y están esperando algo para leer. Y esto solo está bloqueando cualquier ejecución posterior para ese hilo fuera para todo el programa, solo para ese hilo. Entonces lo estoy, por eso queremos asegurarnos de que solo proporcionemos suficientes valores hechos aquí para asegurarnos de que cada instancia de la garganta que tenemos realmente estalla. Y sí, sigamos adelante y ejecutemos esto. Éste debería ser un poco más lento ya que en este momento sólo tenemos una instancia de nuestro hilo. Eso es exactamente lo que vemos aquí. Simplemente estamos extrayendo nuestros valores y estamos poniendo nuestros valores en la cola aquí. Y una vez que empieza un valor, ya sabes, está en esta cola, ahí es cuando nuestro trabajador aquí comienza. Por lo que ya se inicializó de antemano y ya está empezando a ejecutarse. Y tan pronto como lo inicializamos en entra este bucle, y luego hace esto. Y ahora solo está esperando hasta que haya algo en la cola. Una vez que haya algo en la cola, va a leer de ella. Tan pronto como se ponga aquí el primer símbolo, se va a empezar a leer desde él. Si queremos, podemos ver que podemos agregar un sueño y digamos que duerma por diez segundos. Y podemos decir insertar primer símbolo. Entonces, solo echemos un vistazo a eso. Entonces vamos a insertar el primer símbolo y luego vamos a esperar a que se inserte un símbolo. Pero en cuanto se inserta, hay un valor en el planificador de precios de Q y R Yahoo Finance que ya se está ejecutando en cuanto que algo está en la cola, entonces puede sacarlo de la cola aquí y puede empezar a hacer su trabajo. Entonces en cuanto algo esté en la cola, entonces empieza a hacer su trabajo. Lo cual es realmente bonito porque este tipo de hace que todos los procesos sean independientes entre sí. Está bien, Así que por supuesto que podemos quitarle esto. Y ahora si queremos hacer esto un poco más rápido, todo lo que tenemos que hacer es solo, ya sabes, digamos num, Yahoo Finanzas, trabajadores de precios. Digamos que queremos tener para los trabajadores. Y podemos decir por cuantos trabajadores quieran tener, ya sabes, solo creamos uno de estos. Y así ahora tendríamos en este caso, para los trabajadores que están corriendo cada uno de ellos esperando leer de la cola. Y siempre que algo se ponga en la cola aquí, van a empezar a consumir de ella y van a empezar a hacer su trabajo, como podemos ver aquí. Y nuestras colas son seguras para subprocesos, lo cual es realmente bonito porque, ya sabes, no tenemos que lidiar con ninguno de los temas de los que hablamos de antemano. Y está bien, así que ahora estamos consiguiendo algunos buenos valores aquí, vale, con los que tenemos que lidiar. Por lo que el precio es demasiado alto. Entonces una cosa que podemos hacer aquí es hacer algo de formateo y llamar a esto el precio en bruto. Y parece que hay una coma para miles. Entonces sólo vamos a reemplazar eso por una cadena vacía como esta. Sólo para arreglar donde no estaba, como estas cosas de formato. Entonces sí, ahora hemos llegado a un punto realmente bonito porque como que tenemos esta independencia entre nuestras diferentes señales. Ahí vamos. Por lo que podemos ver que los miles también están trabajando. Tenemos esta independencia entre nuestros diferentes hilos porque uno puede, esto no es ni siquiera, quiero decir, esto sería parte de nuestro hilo principal. Es sólo poner valores en la cola. Y cada vez que se pone algo, aquí tenemos a nuestros diferentes trabajadores que están listos y disponibles para empezar a consumir de él. 8. Crea un trabajador de posgres: Está bien, así que ahora sigamos adelante y trabajemos en nuestro trabajador de inserción de bases de datos. Por lo que sólo voy a usar mi base de datos local Postgres. Estoy usando grupo de datos aquí, pero por supuesto puedes usar cualquier entorno de codificación, ya sabes, disfrutas más o codificando IDE. Sí, Si no estás súper fresco en cómo crear tu base de datos Postgres, solo asegúrate de seguir adelante y echa un vistazo al curso SQL. Pero por lo demás, sí, solo gira un servidor Postgres local. Y luego solo voy a usar la base de datos predeterminada Postgres aquí también. Y sólo vamos a crear una tabla en nuestra base de datos Postgres sólo van a insertar estos valores en. Entonces voy a decir crear mesa, y llamaremos a esto precios. Y vamos a tener una columna de identificación que va a ser cereal y sólo vamos a ser nuestra clave primaria. Y entonces también vamos a tener el símbolo, que va a ser a, sólo tener b, el texto. Y luego vamos a tener precio, que va a ser un número de punto flotante. Y entonces también vamos a tener el tiempo, o llamaremos a esta hora de inserción. Deseos sólo va a ser un, bueno, sólo vamos a tener que sea una marca de tiempo. De acuerdo, entonces es una tabla de base de datos bastante simple que estamos teniendo aquí solo va a ser una tabla individual aquí con el individuo o ser una sola tabla con los precios aquí vamos a tener nuestra columna de identificación, que sólo va a estar en serie como nuestra clave primaria. Y luego sólo un símbolo así como el precio y el tiempo. O tal vez en lugar de insertar el tiempo, acabaremos de extraer el tiempo. Entonces el tiempo que lo conseguimos del sitio. De acuerdo, así que sigamos adelante y corramos eso. Y ahí vamos. Al volver a nuestro directorio de subprocesos aquí se creó un nuevo trabajador, que va a ser nuestro trabajador de Postgres. ¿Todo bien? Y aquí vamos a tener dos cosas. Simplemente va a ser nuestro programador maestro Postgres, que va a ser una instancia del hilo de enhebrado como teníamos antes. Al igual que hicimos por el trabajador de precios de Yahoo Finance. Y vamos a excepto argumentos de palabra clave así como una cola de entrada. Y luego solo inicialicemos a los padres pasando los argumentos de palabra clave. Establece la cola de entrada para que sea la cola de entrada que tomamos de la inicialización. Y luego anular el método de ejecución. Al igual que lo hicimos para el trabajador de Yahoo Finanzas. Y diremos aquí, de nuevo, vamos a estar mirando nuestra cola de entrada. Y sólo vamos a esperar hasta que consiga el siguiente valor. Y sin valor se hace, y vamos a salir de nuestro bucle. Muy bien, Así que eso básicamente va a ser la esencia de nuestro anfitrión Chris programador maestro, exactamente lo que hicimos aquí para el trabajador de Yahoo Finanzas. Y por supuesto, no olvidar, queremos asegurarnos de que iniciamos el hilo T2 una vez inicializamos o creamos una instancia de nuestra clase. Muy bien, entonces ahora tenemos que hacer lo otro, que sólo va a estar tratando a nuestro actual trabajador de Postgres, que va a ser el responsable de insertar aquí los datos en nuestra base de datos. Y éste en el método de inicialización. Esto va a tomar el símbolo así como el precio como entrada, y tal vez también el tiempo extraído. Simplemente va a tomar todos estos valores como entrada. Y podemos limpiar esto en un poco y hacer, que esto sea una especie de diccionario como entrada o algo donde puedas sacar los valores de. Frenólogo, deja esto tal como está. Entonces vamos a tener nuestro símbolo B, el símbolo de entrada. Vamos a tener nuestro precio sea, el precio de entrada, vamos a tener. El extracto del tiempo. Si extraes un tiempo aquí, ¿de acuerdo? Y ahora básicamente necesitamos el método que se va a insertar en la base de datos. Y esto va a estar haciendo nuestra inserción. Y en nuestra inserción aquí básicamente necesitamos, en primer lugar, necesitamos crear la consulta de inserción. Y entonces lo que tenemos que hacer es que necesitamos realizar la inserción. Entonces vamos a tener la consulta Crear, insertar ser un método separado. Simplemente vamos a crear la consulta para nosotros para que podamos recuperar eso. Y luego vamos a realizar la inserción. Entonces para crear la consulta, vamos a hacer es, solo vamos a hacer esto usando SQL crudo aquí. Vamos a decir insertar en precios, valores. Y luego vamos a, bueno, hay diferentes formas en que podemos hacer esto. Una de ellas es que podemos usar el formato e, f aquí para decir, bueno, también es definir aquí el interés de orden de columna para ser seguro, precio y tiempo extraído. Vamos a asegurarnos de que eso encaja con nuestra sintaxis. Entonces pon esto en una nueva línea solo para que quede más claro. Entonces de nuevo, la primera forma en que podemos hacerlo es usando las cadenas f. Al igual que esto. Simplemente tipo de formateo en los valores directamente. Al igual que esto. Esto está bien. Porque estamos haciendo esto internamente. Y no hay como entrada externa, pero no es la mejor. En realidad hay una mejor manera de que podamos hacer esto, que es tener el tipo de formato de texto que se haga con nosotros. Y simplemente proporcionamos como aquí va a ser el símbolo que proporcionará más adelante. Aquí va a ser el precio, y aquí va a estar el tiempo extraído. Y entonces tampoco necesitamos tener aquí la cuerda f. Y sí, esta es básicamente la consulta SQL que es, ya sabes, que necesitamos tener. No es mucho, pero está bien. Y entonces sólo vamos a dar vuelta a esta consulta. Entonces otra vez, lo primero que vamos a hacer aquí es que vamos a tener la consulta de inserción solo se cree para nosotros. Y ahora realmente necesitamos realizar la inserción de la base de datos en la inserción de la base de datos, necesitamos configurar una conexión de base de datos. Y para ello, vamos a usar una biblioteca llamada alquimia SQL, que sólo nos va a ayudar mucho. Lo cual sólo nos va a ayudar mucho como configurar la conexión de base de datos, ejecutar estos comandos SQL. Y es realmente igual a una biblioteca general que podemos usar para simplemente conectarnos a bases de datos. Pero te mostraré por ahí como lo esencial justo en un segundo aquí. Pero lo primero que tenemos que hacer es que lo instalemos. Por lo que vamos a pip instalar alquimia SQL así. Y luego en un segundo, entonces también vamos a pip instalar pasteles P. Y realmente espero que soy columna vertebral está correctamente. Pero si no, lo buscaré en un segundo. Pie scopy binario. Tiene un error tipográfico. Entonces probemos eso. Y es alto. Ahí está. Entonces esto es pip install pi, psi. Siempre tener shallower recordando la pronunciación de la misma, que es, nunca podré escribirla. Psi cop G a binario. Y esto nos va a permitir montar las conexiones Postgres. Entonces vamos a instalar alquimia SQL. Ni siquiera necesitamos importar psycopg2. Vamos a instalar la versión binaria porque a veces es si no tienes celda la versión binaria, son como problemas con la instalación. Entonces solo siempre instaló una versión binaria, pero esto simplemente básicamente nos va a proporcionar el controlador que SQLAlchemy puede usar para conectarse realmente a la base de datos. Entonces sí, ¿cómo podemos ir a configurar esta conexión de base de datos mientras hacer eso? Por lo que ya podemos ver aquí ya lo he importado. Pero vamos a usar este método de creación de motor. Y vamos a crear un motor. Y el motor nos va a permitir interactuar con nuestra base de datos. Entonces primero, necesitamos obtener todos los parámetros de nuestra base de datos. Simplemente vamos a ser nuestro nombre de usuario de Postgres. Y una buena manera de hacer esto es establecer esto como una variable de entorno. Postgres. Usuario. Entonces vamos a conseguir la contraseña de Postgres, que también necesitamos contraseña de Postgres. Y luego también vamos a necesitar el host o la URL o donde sea que se encuentre. Por lo que va a ser anfitrión de Postgres. Y luego también vamos a necesitar obtener la base de datos a la que necesitamos conectarnos en el servidor Postgres. Por lo que estos son los detalles de conexión que necesitamos. Y a partir de esto podemos entonces crear una cadena de conexión que nos permitirá conectarnos a la base de datos. Entonces lo otro que he hecho aquí es que he usado el paquete del sistema operativo, que en realidad es importante para mí sólo porque es realmente agradable. Pero esto sólo me permite acceder a cosas desde nuestro sistema operativo específicamente aquí entrando en el ambiente dot y me permite acceder a unas variables de entorno que puedo obtener. Por ejemplo, aquí, voy a usar el punto getMethod. Ahora si no has visto esto antes con el método dot get, es si creamos como un diccionario por ejemplo, y solo creamos una variable aquí. Si haces x dot get, desafortunadamente significa, Vamos a renombrar ese x-dot de nuevo. A va a obtener el valor de este diccionario. Por ejemplo, si haces x-dot Gatsby, que no está incluido en el diccionario, es solo que nos des ninguno. Entonces de esta manera, en lugar de hacer esto, que puede fallar si estamos accediendo a valores que se incluyen, el getMethod o bien nos da el valor vuelca ninguno para que no falle. Y entonces lo que realmente podemos hacer es que podemos usar un o aquí, que lo que pasa es, por ejemplo, si haces en stock obtienes B o luego podemos proporcionar como un valor por defecto que queremos usar. A debe ser una cadena y un entero, entero o lo que sea. Por lo que podemos ver si el valor no existe, obtenemos el valor predeterminado. Y si existe, entonces obtenemos el valor del getMethod aquí. Entonces vamos a decir conseguir a nuestro usuario de Postgres, o simplemente va a estar vacío. O sólo va a estar vacío. O es solo apuntar a tu anfitrión local, o va a ser Postgres. Ahora bien, si tienes postgres corriendo en un Mac y lo instalaste, entonces es muy probable que tu Postgres local no tenga nombre de usuario ni contraseña. Pero si lo estás ejecutando en Windows, es muy probable que tengas un nombre de usuario y una contraseña. Es probable que el nombre de usuario sea Postgres, pero la contraseña va a ser lo que establezcas tu instalación. Entonces recuerda que si estás en Windows, es muy probable que esto vaya a ser repentino o Alice se va a quejar de que se puede conectar porque la contraseña no es ninguna o no se pudo autenticar o lo que sea. Pero en un Mac, no vas a necesitar establecer un nombre de usuario y una contraseña porque probablemente no lo configuraste a menos que lo establecieras explícitamente para tu base de datos. Entonces de nuevo, lo que estamos haciendo aquí es o estamos tratando de obtener estos valores de nuestras variables de entorno o si no están disponibles, seleccionamos valores predeterminados. Y esto en realidad es realmente agradable porque entonces podemos configurar diferentes entornos, variables de entorno para diferentes entornos. Por ejemplo, puede tener un entorno de pruebas, entorno de producción o un entorno de pruebas local. Si no establece nada, entonces solo tomamos nuestros entornos de pruebas locales. De lo contrario tomará las variables que establezcamos. Entonces ahora que tenemos unas variables de entorno difíciles aquí, podemos crear nuestro motor el cual nos va a permitir conectarnos a una base de datos. Vamos a usar el método de motor de caja que obtuvimos de SQLAlchemy. Y sólo vamos a usar cadenas f para esto. Entonces la primera parte, sólo va a indicar que se trata de una conexiones Postgres. Vamos a hacer PostgresSQL, barras inclinadas de punto y coma. Y luego vamos a tener a nuestro usuario o. , vamos a reutilizar o punto y coma, lo siento, colon, colon, colon, la contraseña en la dirección de host, ¿cómo llaman a eso? Sí, Apigee. La dirección de host o la dirección IP o lo que sea, slash, la base de datos. Entonces esta es nuestra cadena de conexión aquí, nombre de usuario, contraseña, host, dirección, y la base de datos a la que nos estamos conectando. Muy bien, entonces ahora tenemos nuestra configuración de motor aquí. Tenemos nuestra consulta SQL que hemos creado aquí. Lo bonito del motor es que nos proporciona un medio para crear conexiones de base de datos. Pero hasta que realmente inicialicemos una conexión a base de datos, no se está creando Conexión. Es solo, bueno, básicamente es solo una clase que nos permite crear esta conexión una vez que explícitamente le decimos que lo haga. Entonces ahora sigamos adelante y ejecutemos esta consulta. Vamos a decir ancho. Y luego usando nuestro motor, nos vamos a conectar. Ahora hay diferentes métodos que podemos usar aquí. Una de ellas es dot connect, que solo crea una conexión. También podemos hacer no empezar, lo que crea una conexión y comienza una transacción. Pero realmente no necesitamos usar las transacciones aquí. Entonces sólo vamos a crear una conexión. Y vamos a tener esto estar en nuestra variable con aquí. Y te darás cuenta son todos recordar la sintaxis desde también como abrir archivos desde nombre de archivo abierto y luego como leerlo como un todo en archivo, esta es exactamente la misma sintaxis que tenemos aquí donde abrimos un archivo, entonces podemos hacer algo con un expediente. Y una vez que salgamos de esta declaración de ancho, el archivo también está cerca para nosotros. Entonces tenemos aquí este Context Manager, lo cual es realmente bonito porque creamos la conexión con él. Podemos acceder a la conexión usando esta columna variables cuando la llamo. Y una vez que salimos de este bloque ancho, la conexión se cierra automáticamente para nosotros, por lo que ni siquiera necesitamos preocuparnos por eso. Por lo que ahora solo podemos usar nuestra conexión. Y con nuestra instancia de conexión aquí, podemos tener este método no ejecutar, que nos va a permitir ejecutar aquí esta sentencia SQL. Ahora hay una cosa más que tenemos que hacer, que es que necesitamos proporcionar esta entrada, ya que no proporcionamos aquí como cadenas f. Por lo que necesitamos proporcionarlo cuando estamos haciendo la inserción. Ahora para proporcionar formato para esta sintaxis, en realidad necesitamos importar alumbre, una clase especial que nos permitirá hacer eso desde SQLAlchemy dot SQL. Vamos a importar texto. Y luego vamos a envolver esto en el texto aquí. Y entonces vamos a proporcionar nuestra aportación aquí. Entonces vamos a tener nuestro símbolo, que es este símbolo de colon, o símbolo, va a ser el símbolo aquí. El precio va a ser el precio. Y el extracto un tiempo. Va a ser el tiempo extraído aquí. Está bien, así que repasemos esos una vez más. Entonces tenemos a nuestro trabajador de Postgres, que toma en el símbolo, el precio así como el tiempo extraído como variables de entrada. Y luego también crea una, una instancia para una conexión de base de datos con la dirección de conexión postgres. Y entonces en realidad vamos a llamar, es que vamos a llamar insertar dos base de datos. Y va a crear la consulta SQL para nosotros. Entonces nos vamos a conectar a la base de datos. Entonces vamos a crear una conexión con la base de datos. Y con esa conexión, vamos a ejecutar la sentencia SQL que hemos creado aquí. Vamos a utilizar este formato de texto aquí porque tenemos este formato especial cual básicamente nos permite alguna protección contra como impuesto de inyección. Entonces sólo que el formateo sea adecuado. Y entonces realmente podemos proporcionar el formato aquí como solo una segunda variable de entrada y algún diccionario muy simple. Y luego va a llenar los valores para nosotros. Y luego una vez que salgamos de esta declaración de ancho, La conexión también se va a cerrar automáticamente para nosotros porque estamos usando esto con declaración aquí. Entonces un muy conveniente, bien, así que volvamos a nuestro programador maestro. Y lo que tenemos que hacer aquí es una vez que obtengamos un valor de nuestra cola de entrada, aquí, entonces vamos a crear una instancia de nuestro trabajador de Postgres, asegurándonos de proporcionar el símbolo, el precio, así como el extracto un tiempo. Y así estamos, vamos a sacar eso de, bueno, y supongamos que eso es lo que vamos a conseguir con nuestro valor de entrada aquí. Entonces nuestro valor de entrada aquí que o va a ser una lista que se ve así, o va a ser una tupla que se ve así. De cualquier manera, porque tenemos control total sobre esto, vamos a suponer que así va a ser como obtuvimos nuestros datos. Por supuesto, ya sabes, podemos hacer que esto sea más general y solo que esto sea como un diccionario. Y entonces podríamos decir símbolo es igual a la válvula, otra vez símbolo y hacer lo mismo por precio igual Val dot get, Prius y así sucesivamente. Hace que sea un poco menos propenso a errores. Pero, ya sabes, ese no es el propósito de esto ahora mismo. Solo somos, ya sabes, solo queremos que esto funcione. Entonces solo nos vamos a asegurar por ahora que así sea como va a funcionar. Y luego una vez que tengamos nuestra instancia pros Caseworker Aquí, vamos a llamar insertar en base de datos. Está bien, así que esto está creando a nuestro trabajador de Postgres. Ahora vamos a continuar con esto en la siguiente lección porque también necesitamos proporcionar aquí la cola de entrada. Tenemos que enviar estos valores ahí dentro. Y además, necesitamos incluir esto en nuestra función principal aquí, porque esto ya se está haciendo bastante largo. Adelante y detengámonos aquí por ahora y luego continuemos esto en la siguiente lección. 9. Integrar los posgres trabajador: Muy bien, entonces ahora que hemos montado a nuestra chica puerto Postgres, sigamos adelante y sigamos con esto. Integra esto en nuestra función principal, y haz algunos otros cambios en la línea para asegurarte de que todo funcione correctamente. Entonces en primer lugar, en orden, función principal, vamos a importar el programador maestro Postgres. Y vamos a hacer algo similar a lo que hicimos para el trabajador de Yahoo Finance aquí. Esto y esto es en lugar de finanzas, van a ser nuestros graduados post. Y cambiemos la entrada en cubos y un segundo. Y sólo actualizando los nombres aquí. Ahí vamos. Y NAIM, trabajador post posgrado, así y la cola de entrada. Entonces ahora necesito una nueva Q. Y eso va a ser un taco VIP Postgres así. Está bien, así que tenemos un postgres programador hilos aquí, número de trabajadores de podcasts, supongamos a dos. Por ahora, sólo veamos cómo van las cosas. Programador Postgres, que va a ser instancia arriba para el programador maestro Postgres, que va a tener esta cola de entrada aquí. Y usted está haciendo un seguimiento de esas amenazas. Muy bien, entonces ahora que tenemos este Postgres Q, realidad necesitamos meter valores en ella. Y así vamos a tener que esto sea una cola de salida. Top lo vamos a proporcionar a un programador de precios de Yahoo Finance. Ahora bien, hay dos maneras en que podemos ir por esto. El primero es por supuesto que podemos hacer explícitamente que sea un argumento de entrada. O en realidad podemos simplemente usar nuestros argumentos de palabras clave aquí. Y luego vamos a decir, vale, entonces tenemos en nuestra salida OOP, o salida Q, ¿va a ser? Y luego a partir de nuestros argumentos de palabra clave, vamos a obtener la salida Q. Y si esto no existe, esto va a ser ninguno. De lo contrario. Sí, vamos a conseguir valores de aquí. Muy bien, entonces durante el método de ejecución, tenemos el precio aquí. Y entonces podemos decir, si la salida Q no es, no, entonces en nuestra salida Q, vamos a poner este precio. Del mismo modo. Una vez que terminemos aquí, sigamos adelante y solo asegurémonos de que también enviamos hecho a nuestros marcadores aguas abajo. Muy bien, entonces, ¿qué acabamos de hacer? Bueno, agregamos una cola de salida. Y la razón por la que necesitamos una Q de salida es porque ahora tenemos un proceso de tres pasos. El primer paso es conseguir todos los símbolos, lo que estamos haciendo con nuestro trabajador wiki, que no es un hilo. Es solo, bueno, es parte del término principal, pero es solo un trabajador que obtiene todos los símbolos que lo ponen en el símbolo Q. El símbolo Q es leído entonces por el programador de precios de Yahoo Finance, el programador maestro aquí. Y cada vez que obtenga el valor, lo va a procesar y obtener el precio. Ahora en lugar de imprimir el precio, lo va a enviar a la salida Q aquí. Y el resultado Q es lo que nuestro programador maestro Postgres aquí va a estar consumiendo como su cola de entrada, como podemos ver aquí. Y echemos un vistazo a esto. Y una vez que terminemos, una vez que salgamos, queremos asegurarnos de que también ponemos en la salida Q y terminamos. Entonces lo que los trabajadores aguas abajo son también, ya sabes, conseguir que este mensaje hecho les pase a ellos. Ahora algo importante a tener en cuenta es el formato que estamos esperando aquí. Aquí, como esperamos el símbolo, el precio, así como el extraído al tiempo. Por lo tanto, vamos a establecer esos para que sean los valores de salida de salida. Por lo que hay que proporcionar el símbolo aquí, que va a ser el valor que obtengamos de aquí, el precio, así como el tiempo extraído, que sólo vamos a convertir esto en un entero. Y eso es lo que vamos a poner en tu salida Q. Desde otra vez, nuestro trabajador de Postgres está esperando el símbolo y luego el precio y luego el símbolo de tiempo extraído, porque están consiguiendo eso de la cola de entrada, que tiene el símbolo Q. Precio. Y luego el tiempo extraído justo aquí. Y estos valores que vamos a poner en nuestra salida Q. Y luego los vamos a leer aquí como nuestra cola de entrada en nuestro trabajador de Postgres. Está bien, entonces, sí, y luego vamos a mandar el valor w1, que podemos llegar hasta aquí. De acuerdo, así que sigamos adelante y, sigamos adelante y probemos esto. A ver cómo están funcionando las cosas si hay algo que nos perdimos. Obtuvo una inesperada salida de argumento palabra clave Q. ¿De acuerdo? Entonces, en realidad en este caso, deberíamos definirlo explícitamente porque estamos pasando como argumentos de salida. Y así nos está dando por dónde estamos pasando nuestros argumentos de palabra clave. Y básicamente está diciendo, oh, bueno, bien. La clase de subprocesos que utiliza estos argumentos de palabra clave, no, ya sabes, no sabe qué, cómo manejar las colas de salida. Entonces en realidad lo vamos a definir explícitamente para que no lo pasemos porque está causando errores aguas abajo. Así. Adelante y corremos eso una vez más. A ver cómo van las cosas ahora. Está bien, Ok, Así parece que las cosas están funcionando y estamos consiguiendo que los valores se transmitan. Bud, estamos teniendo algunos problemas al insertar los datos en nuestra base de datos. ¿ Está bien? Y el tema principal parece estar aquí con nuestra marca de tiempo. Y este caso es realmente solo quejarse de que estamos proporcionando un entero aquí, pero está esperando una marca de tiempo. Entonces, solo sigamos adelante e incluimos un casting aquí. Pongamos esto en una nueva línea solo para facilitar el formateo. Entonces vamos a lanzar este valor como una marca de tiempo. Aquí vamos a hacer listas de casting. Vamos a intentarlo una vez más. Sigo recibiendo problemas. Y veamos qué valor estamos pasando aquí. Por supuesto, estamos usando el. Entonces empecemos enviando el valor de tiempo. Oops, queremos enviar básicamente como una instancia de fecha y hora que podemos insertar. Así que así. Y entonces ya no espero que necesitemos esto. Y vamos a seguir adelante y asegurarnos de lanzar esto como una cadena para que obtengamos el formato de cadena. Para que el valor que vamos a conseguir aquí va a ser de así, algo así, lo que sea. Sólo estoy inventando un tiempo, como algo así como este formato. Muy bien, entonces vamos a conseguir eso usando la clase datetime aquí. Entonces vamos a pasar un objeto datetime, que va a ser UTC. Ahora, cuando se utiliza UTC ahora en lugar de ahora, sólo para que todo esté estandarizado y aún necesitamos la biblioteca de tiempo para, al dormir aquí abajo al final. Está bien, sigamos adelante y probemos eso una vez más. Parece que se está ejecutando y en realidad no tendríamos ningún resultado de impresión, pero sigamos adelante y revisemos nuestra base de datos. Tirando hacia arriba una mesa aquí. Ah, ahí vamos. Por lo que se están insertando nuestros valores para nosotros como podemos ver, lo cual es realmente grandioso. Entonces esto es exactamente lo que estamos esperando. Y sí, así que básicamente recapitulemos rápidamente lo que está pasando ahora mismo porque tenemos muchas piezas en movimiento diferentes. Entonces lo primero que tenemos aquí nuestro hilo principal. En nuestro hilo principal, donde luego crear un símbolo Q así como un Postgres q Estos son indicios donde vamos a pasar los símbolos que obtenemos de nuestro depurador wiki. Entonces sólo mirando la página wiki aquí, esto está pasando por todos los símbolos de aquí. Todos los símbolos aquí, y está pasando estos a este símbolo de salida Q aquí. Y entonces nuestro programador de precios de Yahoo Finance, que tenemos cuatro instancias de actualmente, va a estar leyendo desde esta cola. Y luego se va a conseguir el precio o se va a tratar de hacerlo, y se lo va a pasar a la punta Q aguas abajo para hacer. Y se lo va a pasar a la Q aguas abajo, que va a ser nuestro Postgres Q aquí. Y esto va a tomar estos valores. Se va a leer del Postgres Q, que es la salida Q aquí. Y nuestro trabajador de Postgres sólo va a seguir leyendo de esta cola. Y cada vez que obtiene un valor, lo es, sí, lo voy a insertar en la base de datos y vamos a conseguir el valor w1. Entonces se va a salir del bucle aquí. Y nos estamos asegurando de solo, si conseguimos el valor w1 en nuestra entrada aquí, nos aseguramos de pasar eso a la salida Q, que es postgres va a estar leyendo de Sloan. Sí, eso es lo que tenemos pasando. Veamos cuántos registros tenemos ahora en nuestra base de datos. A 180. Entonces estamos esperando. 550. Y otra vez, esto va bastante lento, sólo porque estamos tenemos esta cosa del sueño pasando aquí para especie de limitar lo rápido que van. Porque por supuesto esto podría estar funcionando mucho más rápido. Entonces, sólo para asegurarse de que esto esté terminando correctamente, en lugar de conseguir todos los símbolos. Yo sólo voy a tener un símbolo o no. Sí, tendremos un contador de símbolos. Y cada vez que insertemos un símbolo, vamos a aumentar esto en uno. Y entonces digamos solo para asegurarnos de que esto funcione correctamente. Si, oh, vamos, si tenemos al menos cinco símbolos, vamos a salir de esto sólo para asegurarnos de que no tengamos que esperar todo el camino hasta llegar aquí como 550, sólo para ver si eso funciona correctamente. Entonces vamos a dejar de lado esto, volver a ejecutar esto. Y ahora debería ir mucho más rápido. Deberíamos estar yendo cinco símbolos los cuales deberían insertarse en la base de datos. Y entonces todo debería estar saliendo, lo que hace. Genial. Entonces eso es importante para nosotros porque si no fuera salir, eso significa que nuestros hilos están colgando en alguna parte, que todavía hay un hilo activo en alguna parte. Y podemos ver que eso es lo que obtendríamos. Si no hicimos esto. Entonces nuestros trabajadores de Postgres nunca serían contados , ya sabes, hechos y simplemente continuarían. En realidad, parece que no nos estamos uniendo, que es lo que vemos aquí. Pero, ya sabes, no estamos saliendo porque nuestros Postgres, trabajadores están atrapados en este bucle básicamente siendo bloqueados por esto. Están esperando obtener el siguiente valor, pero la cola está vacía y no se está poniendo nada en la cola. Así que sólo se quedó aquí para siempre, así que no va a parar. Entonces por eso es importante que pasemos estos valores para asegurarnos de que las señales descendentes también sean conscientes de que, vale, es hora de parar. Por lo que al salir de esto, hay una cosa más que en realidad podemos hacer para un tipo de ayuda a prevenir esto. Entonces en realidad, Dejemos esto comentado por ahora e ingresemos a nuestro trabajador de Postgres. Y aquí vamos a añadir un tiempo de espera. Y pongamos esto a 10 segundos. Y vamos a decir, está bien, si no tenemos valor en 10 segundos, entonces queremos salir. Entonces vamos a agregar una declaración try and except aquí y obtener la excepción vacía especial, que podemos obtener de Q. Cola de importación vacía es de nuevo una biblioteca de Python predeterminada. Por lo que sólo podemos importar desde aquí. Y Q de multiprocesamiento, que es lo que hemos importado aquí, en realidad simplemente básicamente implementa directamente la clase de cola de la biblioteca Python de cola estándar. Entonces a partir de aquí podemos obtener la excepción vacía. Entonces si específicamente atrapamos la excepción vacía, entonces solo queremos imprimir Q o timeout incumplidos y Postgres, programador parando. Y luego también aquí, queremos salir. Entonces en este caso, no lo estamos, no estamos enviando la señal hecha a un trabajador de Postgres. Y así va a estar colgando un poco. Y pero va a tener un tiempo de espera aquí. Y en realidad vamos a ver en solo un poquito que los trabajadores de Postgres van a parar de todos modos porque no hay nada en la cola y se ha llegado a los tiempos de espera. Por lo que podemos ver aquí el primer segmento de una parada, parada. Ahí vamos. Entonces por eso es un poco agradable porque, ya sabes, se protege de esperar para siempre. Pero por supuesto, hay que estar al tanto porque si tuviste un tiempo fuera en el tiempo de espera no es lo suficientemente grande como para que los valores entren desde arriba. Ustedes son trabajadores aguas abajo en realidad van a renunciar antes de que alguna vez tuvieran la oportunidad de trabajar. O si hay alguna interrupción en el medio, entonces, ya sabes, tus trabajadores de aguas abajo van a renunciar mientras las cosas siguen pasando. Por lo que hay que tener un poco de cuidado con esto. Ya sabes que no pones tu tiempo para ser demasiado corto porque claro es porque puede causar problemas. Y así, ya sabes, quieres asegurarte de que idealmente siempre terminas enviando algún tipo de comando como salida. Veamos ahora tu QRS. De acuerdo, es hora de, hora de parar aquí. Y por supuesto tenemos el tiempo de espera aquí y podemos hacer lo mismo para que nuestro Yahoo Finance vaya aquí. Vamos a decir, intenta conseguir un valor. Obtenemos la excepción vacía. Vamos a imprimir Yahoo. Programador. La cola está vacía. Y luego vamos a decir que nos vamos a parar, vamos a salir. Y vamos a decir para Q y puerto vacío. Esto, sólo voy a reorganizar aquí un poco las importaciones. Que todas las bibliotecas por defecto están en la parte superior aquí. Y todas las bibliotecas instaladas están en la parte inferior. Por lo general. Ahí vamos. Simplemente proporciona una estructura un poco más fácil que sabemos que todos son valores predeterminados y estos los tuvimos que instalar. De acuerdo, Entonces y todo lo que también hemos agregado saliente en realidad no fijó un tiempo de espera aquí. Por lo que también estamos estableciendo un tiempo de espera aquí por si acaso. Pero claro, ya sabes, ten cuidado con esto porque puedes hacer que tus trabajadores salgan mientras que en realidad deberían seguir trabajando porque hay algún tipo de retraso pasando aguas arriba. Y en realidad no necesitamos ningún argumento de palabra clave aquí. Por lo que podemos simplemente sacar estos para imprimir declaración aquí tampoco. Está bien, sí, así que ahora tenemos a nuestros trabajadores configurados a uno de ellos, especie de conseguir los símbolos de aquí. Por cada símbolo que obtenemos, lo pasamos para obtener los datos de Yahoo Finance. Y por cada precio que obtenemos, ponemos eso en un q aguas abajo, que son trabajadores de Postgres van a consumir de. Ahora sólo quedan algunas pequeñas cosas por hacer, que sólo va a estar haciendo el join al final aquí. Por lo que vamos a repasar Postgres, amenazas programadoras, y sólo llamar se une al final aquí. Y en realidad voy a cambiar la lógica de nuestro QS de salida aquí un poco, porque es posible que, ya sabes, este momento estamos asumiendo que tenemos una salida Q, pero tal vez queremos tener más de una salida Q. Entonces para tipo de acomodarse para eso, voy a leer esto en una variable temporal. Voy a decir que si nuestra Q temporal no es mucha lista, entonces sólo quiero que esto sea una lista. Por lo que ahora nuestra salida QS va a ser una lista que puede ser una, pueden ser varias. Y entonces tenemos que por supuesto, cambiar un poco esto. Y porque ya no vamos a conseguir ninguno aquí. Entonces lo que podemos hacer es decir para la salida Q en las colas de salida. Y luego por cada salida Q, vamos a enviar on hecho. Y si aquí no hay elementos, entonces esto va a estar vacío. Por lo que no hay colas de salida, entonces esto va a estar vacío. De lo contrario, ya sabes, si tenemos uno, entonces vamos a tener uno. Y si tenemos más de uno, entonces vamos a tener más de uno. Y en realidad podemos sí. Está bien. Entonces sí, así que ahora acabamos de hacer esto un poco más agradable porque podemos proporcionar esto como una lista de entrada. Y en realidad hagamos eso también, pesar de que sí aceptamos sólo la variable específica. Pero esto sí proporciona esto como un insumo, como una lista. Entonces, ¿podemos tener una q aguas abajo? Vamos a seguir adelante y ejecutar esto una vez más para asegurarnos de que esté funcionando. Pero de esta manera ahora tenemos un poco más de flexibilidad porque tal vez se olvidó de cambiarlo aquí. Ah, ahí vamos. Cuatro, salida Q y salida QS. Ahí vamos. De acuerdo, así que ahora tenemos un poco más de flexibilidad porque tal vez no sólo queremos guardar esto en una base de datos, sino tal vez queremos guardar esto en múltiples bases de datos. Entonces lo que podemos hacer es que podemos tener aquí a nuestro principal trabajador de Yahoo Finance, en lugar de tener solo una salida Q. Puede tener una múltiples colas de salida y diferentes trabajadores downstream. Entonces podemos decir que tenemos un trabajador de Postgres. También podemos tener como he leído trabajador estadounidense o trabajador MySQL o cualquier otra base de datos que tenga. Cada uno de ellos puede estar consumiendo de las diferentes señales que aquí brindamos. Y nuestro trabajador de Yahoo Finance solo estará escribiendo a cada salida Q. Así que cada salida Q que tenemos, vamos a escribir estos valores también. Y luego los trabajadores de aguas abajo pueden, ya sabes, usar todas estas cosas y básicamente obtenemos las de precio, pero podemos reutilizarla en especie de ponerla en las diferentes señales para que los diferentes trabajadores puedan consumir de ellos. Y así esto nos da más flexibilidad porque, ya sabes, no siempre va a ser uno dentro, uno fuera. A veces no va a haber salida. A veces va a haber múltiples salidas. Y así esto nos proporciona sólo un poco más de flexibilidad en ese sentido. 10. Introducción a los archivos de Yaml: Está bien, entonces ahora que tenemos implementado este programa de trabajo, sigamos adelante y limpiémoslo un poco. Que sea un poco más agradable tener una visión general además de poder ampliarla más adelante si queremos, sin realmente siempre solo tener que añadir nuevos fragmentos de código o copiar pegar o cambiar la lógica ahí dentro. Entonces en cambio lo que vamos a hacer, y en realidad vamos a definir esto en algún tipo de archivo donde específicamente podemos decir que estas son las señales que tenemos, ya sea los trabajadores que tenemos. Y eso definirá como nuestro programa aquí. Y entonces lo que vamos a hacer es que vamos a escribir un archivo YAML. Y eso es lo que vamos a cubrir en esta lección, escribiendo el expediente así como cómo podemos leerlo y realmente lo que significa para nosotros. Entonces para ello, vamos a empezar y crear un nuevo directorio aquí. Y voy a llamar a esto Tuberías. Puedes llamarlo como quieras. Voy a llamar a ductos porque lo que tenemos aquí tipo de en el ducto, empezamos con describir los datos brutos del sitio de Wikipedia, pasándolos a ellos, ser extraídos del letrero de Yahoo, y luego pasarlo en para ser subido a Postgres. Entonces eso va a ser un ducto para nosotros aquí. Y así aquí dentro voy a crear un nuevo archivo. Y ese va a ser nuestro wiki, Yahoo, chatarra o ducto, y llamarlo punto YAML. ¿ Por qué ML? Ahora para poder leer este archivo en Python, y solo haremos ese tipo de bit a la vez. También vamos a activar mi entorno virtual aquí. Pero voy a ir PIP y tropezar. Pi YAML. Golpea entrar aquí y deja que eso se instale. Y esto es una especie de ahora y la biblioteca que necesitábamos para poder leer esto. Y así en un segundo, cuando escribamos este archivo YAML, podemos usar la biblioteca de tartas, que luego simplemente convertirá esto en una básicamente como una especie de lista anidada o estructura de diccionario para nosotros que veremos en un segundo. Entonces lo primero que queremos, si solo miramos aquí nuestro programa principal, es si tenemos colas. Por lo que de alguna manera necesitamos definir las señales que queremos. Y entonces también tenemos trabajadores. Estas son como las esencias de lo que queremos. Entonces voy a definir por aquí, y sólo voy a decir, está bien, estas son las señales que queremos. Y solo voy a escribir esto un poco y luego en un segundo lo vamos a leer y, ya sabes, podemos explorar un poco cómo este archivo YAML transforma realmente en una estructura de datos de Python. Entonces aquí, voy a simplemente enumerar básicamente las señales. El primero, le voy a dar un nombre. Y eso aquí va a ser, si volvemos a nuestra función principal aquí, va a ser el símbolo Q. Así que voy a llamar a este símbolo Q, llámalo como quieras. Y también le voy a dar una descripción. De nuevo, no te preocupes por esto ahora mismo. Voy a recuperar esto en un segundo. Yo sólo quiero tener algo aquí para que podamos verlo. Y este va a ser el contiene símbolos para ser desguazado de Yahoo Finanzas. Y luego queremos tener otra Q, que va a ser nuestra Postgres subiendo. Y la descripción aquí va a ser contiene datos que necesitan ser subidos. Postgres. Y entonces también tenemos trabajadores. Y los trabajadores. El primero aquí, si solo miramos esto, va a ser nuestro trabajador wiki o podemos, sí, vale, trabajador está bien. Aquí podemos dar una descripción. Esto descarta página cruda de Wikipedia y saca símbolos. Y luego otra vez, como que vamos a repasar esto iterativamente. Pero quería tener el tipo de base como ubicación o podemos encontrar a este trabajador. Por lo que va a ser en trabajadores punto clave trabajador. Y la clase que queremos usar va a ser esta clase de trabajador wiki que voy a poner aquí. Y entonces también queríamos encontrar colas de entrada, etcétera, eso, a las que llegaremos en un rato. Pero dejémoslo en esto. Entonces ahora tenemos algo que ver en realidad. Y luego sigamos adelante y carguemos esto y veamos cómo esos archivos YAML realmente se traducen en algo utilizable en Python. Entonces solo voy a lanzar Python sobre mi terminal aquí. Y voy a importar YAML, que ahora podemos hacer porque instalamos PMO previamente. Ahora lo que voy a hacer es que voy a decir con abierto. Líneas de tubería. Y sólo voy a copiar este nombre aquí porque probablemente lo escribiré mal. Y luego tendremos que encontrar el tipográfico. Voy a abrirlo en modo lectura. Voy a decir, llama a esto nuestro infile. Y otra vez, solo repasemos esto y luego como que recapitularemos todo lo que hemos hecho. Haremos un poco de exploración, pero primero necesitamos tener algún tipo de base. Y así nuestros datos YAML sólo van a ser, y luego vamos a usar nuestra biblioteca YAML. Vamos a hacer carga segura. Y vamos a poner un aquí, nuestro archivo de arte justo en el que lo hemos leído para golpear Enter. Está bien, así que lo hemos cargado. Entonces sigamos adelante y echemos un vistazo a esto. Entonces podemos ver es que nuestros datos YAML es en realidad, y si nos fijamos en su tipo, es un diccionario. Entonces la primera clave que tenemos son las claves que tenemos. Si miramos las llaves, es que tenemos dos llaves, tacos y trabajadores, y eso es exactamente lo que tenemos aquí. El primero es una q, y el segundo es un trabajador. Y casi ahora puedes ver lo que obtenemos en Python, puedes reconocer la estructura aquí, ¿verdad? Entonces tenemos básicamente este tipo de formato de diccionario familiar donde tenemos el nombre y luego el punto y coma, y luego tenemos los valores contenidos dentro. Ahora lo que podemos ver aquí está dentro de señales, en realidad tenemos una lista. Entonces sigamos adelante y tomemos nuestros datos YAML. Vamos a buscar en las colas. Por lo que aquí tenemos una lista. Y la razón por la que obtenemos una lista es porque en realidad usamos estos guiones que indican elementos de lista. Entonces en este caso tenemos que enumerar elementos aquí. Pero si miramos por dentro, digamos que el primer elemento de lista volverá a ver aquí tenemos un diccionario como lo hacemos aquí. Entonces podemos ver que tenemos como una forma repetida fuera de primero estamos definiendo tipo de claves de diccionario. Entonces dentro estamos definiendo los contenidos. Y luego dentro, en este caso estamos usando elementos de lista indicados por un guión. Y luego dentro de aquí otra vez tenemos un diccionario que podemos ver aquí. Tenemos el nombre, que es el nombre aquí, y tenemos la descripción. Ahora, cuando estoy escribiendo esto, puede que hayas pensado, Oh, estás usando palabras clave específicas para especie de indicar todas estas cosas. No lo sé. Acabo de decidir usar la descripción del nombre, clase de ubicación porque son convenientes y son claros para el programador cuando estás leyendo esto, son muy descriptivos y claros, pero ya sabes, realmente no le importa qué usaría. Realmente nos vendría bien cualquier cosa aquí porque de nuevo, sólo estamos consiguiendo diccionarios y listas de aquí que podemos usar. Pero sólo para facilitarnos la vida, ya sea cuando lo escribimos ahora o cuando volvamos a ella, cuando queremos mostrársela a otras personas, queremos asegurarnos de que usamos nombres descriptivos para que, ya sabes, sea amable de claro lo que está pasando. Entonces algo que también podemos hacer en realidad, que puede ayudar a despejar un poco la sintaxis. En lugar de usar esta sintaxis aquí abajo, en realidad podemos usar una sintaxis como esta y el resultado, pero vamos a conseguir va a ser el mismo. Entonces, solo volvamos aquí arriba y vamos a recargar nuestros datos. Y luego echemos un vistazo nuevamente a nuestros datos de YAML. Y podemos ver aquí los valores que obtenemos aquí son, nota que tengo un tipografía y descripción aquí. Pero podemos ver que los valores que obtenemos aquí siguen siendo los mismos, ¿verdad? Nada se cambia en el mismo formato exacto está aquí. Ahora esta es sólo una forma diferente de representarla. Entonces si quieres, este tipo de casi lo trae de vuelta exactamente a la estructura de Python que tenemos a la que estamos un poco acostumbrados en Python, excepto por supuesto que usamos comillas ya que en realidad estamos definiendo un diccionario y de lo contrario nos estaría haciendo referencia a nombres de variables. Pero una vez que te acostumbras, este formato puede ser en realidad un poco más limpio de leer que este. Entonces por eso voy a deshacer estos cambios. Y lo voy a tener como que era antes porque se vuelve un poco más limpio de leer. Pero la otra forma es sólo mostrarte un poco, otra vez, tal vez traducirlo de nuevo a cosas como, ya sabes, en Python para que puedas entender mejor qué es exactamente lo que está pasando. Pero podemos ver aquí, de acuerdo, así que hemos definido las señales y de nuevo, llamamos cues porque es conveniente para nosotros, no porque se necesite en ella de cualquier otra manera. Y tenemos aquí de nuevo a estos trabajadores porque es conveniente para nosotros. Por lo que tenemos nuestro trabajador wiki. Y otra vez, aquí estos nombres no tienen por qué ser los mismos. Es solo, ya sabes, poco conveniente y descriptivo de usar, pero podemos llamar a esto algo completamente diferente. Este año es importante porque vamos a estar usando esto más tarde, no ahora, sino más tarde. Lo usaremos para cargar de manera dinámica e inicializar esta clase desde esta ubicación. Por lo que queremos asegurarnos de que esta ruta de ubicación y también podría llamarla una ruta basada en rutas, lo que sea correcto. Y luego aquí dentro queremos asegurarnos de que estamos haciendo referencia al marcador correcto así para que realmente podamos inicializarlo. Entonces tenemos al único trabajador aquí. También quiero poner colas de entrada. Ahora en este caso en realidad no tenemos una cola de entrada. Entonces no lo voy a definir. Pero tal vez queremos pasar como valores de entrada. Y estas pueden ser solo una lista de URL para fregar, por ejemplo. Entonces algo que podríamos hacer es que podemos tomar esta URL aquí que queremos desechar y en lugar de codificarla duro en nuestro trabajador wiki, en realidad podemos definirla aquí. Y luego si tenemos otros sitios wiki que siguen la misma estructura que en realidad nos dejan reutilizar o trabajador, o nos expandimos o trabajamos para especie de poder aceptar estos diferentes sitios. En realidad podemos poner más URL aquí cuando lleguemos a ese punto. O, ya sabes, si alguna vez tienes datos así. Pero ahora mismo sólo vamos a seguir con esto, pero, ya sabes, que sea un poco más general para que estemos definiendo todo por aquí. Entonces tenemos a nuestro primer trabajador. Entonces vamos a crear nuestro segundo trabajador, que si miramos hacia atrás nuestra función principal aquí, tenemos a nuestro trabajador de Yahoo Finance. Entonces este aquí va a ser nuestro trabajador de Yahoo Finanzas. La descripción aquí va a ser tira datos o tira datos precios para un símbolo de acciones específico de Yahoo Finance. Ubicación aquí va a ser punto trabajadores, y yo sólo voy a copiar este nombre aquí para que no haya tipografía porque eso va a ser frustrante. Y la clase que queremos cargar aquí va a ser nuestro joven programador de precios de Yahoo Finance, no los trabajadores de precios van a ser la misma que estamos usando aquí. Entonces esto es lo que queremos usar. Y aquí vamos a tener una cola de entrada sólo tendrá que esto sea una entrada singular q. Y eso va a ser en realidad podemos simplemente mantener directamente esto como diccionario en su lugar. Entonces nuestra entrada q aquí va a ser, bueno, la salida de aquí. Entonces sigamos adelante y definamos QS de salida. Este, vamos a tener un plural en caso de que quieras enviarlo a múltiples cues. Pero por ahora sólo lo vamos a enviar al símbolo Q que aquí hemos definido. ¿ Todo bien? Y de nuevo, sólo estamos haciendo referencia a los nombres aquí porque todas son solo colas generales. Y así podemos referirnos a estas diferentes señales. Estos son, veremos más adelante cómo vamos a usar estos. Pero sí, esto, tener estas convenciones de nomenclatura, sobre todo para el tipo Q simplemente nos deja nombrar correctamente y una referencia todo. Entonces nuestra entrada q aquí va a ser nuestro símbolo Q. Y nuestra salida QS aquí van a ser solo nuestros Postgres subiendo Q. Ahora, la razón por la que quiero tener múltiples salidas QS es tal vez no sólo quiero enviar esta información a uno ubicación en un tipo de trabajador aguas abajo, pero en realidad varios. Entonces tal vez quiero que mi trabajador wiki lo envíe al trabajador de Yahoo Finance para sacar los datos del precio, pero también quiero enviárselo a un trabajador diferente, que solo almacena directamente es todos estos datos crudos en algún lugar y no hace nada más con él. O tal vez hace algo completamente diferente con él. Entonces de esa manera puedo enviarlo a múltiples ubicaciones y diferentes trabajadores de aguas abajo pueden ver estos están leyendo desde aquí. Su aguas abajo puede usar esta información de diferentes maneras. ¿ Verdad? Definamos a nuestro último trabajador. Si volvemos a nuestra función principal, ese va a ser nuestro anfitrión Chris trabajador. Entonces esa de aquí. Entonces aquí vamos a llamar a esto nuestra descripción del trabajador de Postgres. Toma datos de inventario y ahorra en Postgres. Ubicación va a estar comiendo. Trabajadores, trabajadores de punto postgres. Y la clase que vamos a utilizar va a volver a ser el programador maestro. Ya que esa va a ser la que va a leer de la cola y todo. Al igual que lo estamos haciendo en nuestra función principal aquí. ¿ De acuerdo? La cola de entrada. Va a haber postgres subiendo. Y en realidad ni siquiera vamos a definir una cola de salida porque hay, ya no quieres enviar estos datos. Muy bien, entonces estas son una especie de nuestras definiciones de base. Ahora podemos actualizar este archivo YAML más tarde o podemos cambiar un poco ya que estamos pasando. En realidad notamos que tal vez quieras describir las cosas un poco diferente. Pero por ahora, esta es una especie de la descripción base de un programa, por supuesto, ahora mismo no hace nada porque realmente tenemos que hacer uso de él, lo cual haremos en las próximas lecciones. Pero sólo sigamos adelante y leamos esto para que podamos ver lo que tenemos. Y por supuesto, para asegurarse de que esté funcionando. Por lo que echándole un vistazo, tenemos las diferentes señales y trabajadores. Y en las colas tenemos dos colas, el símbolo Q así como los Postgres subiendo. Y en nuestros trabajadores tenemos echándole un vistazo a eso. En nuestro trabajador es tendríamos varios diferentes y tenemos al trabajador wiki, que también tiene valores de entrada aquí, podemos ver que fueron transferidos adecuadamente. Tenemos nuestro trabajador de Yahoo Finanzas se va a referir el joven amigo es programador de precios. Y nuestro trabajador de Postgres, que va a hacer referencia al programador maestro Postgres. Por lo que ahora como que tenemos este ducto completo, definirlo en este archivo YAML. Nuevamente, por supuesto, aún no lo hemos hecho uso. Eso es lo que estaremos haciendo en las próximas secciones. Pero ojalá puedas ver que si podemos transferir la descripción general de cómo funciona un programa, en lugar de como codificarlo todo aquí para tenerlo sea mucho más configurable en este archivo YAML. Eso nos brinda mucha flexibilidad porque una vez que creamos dinámicamente a nuestros trabajadores y los hacemos enviar a cada una de estas colas. Si queremos agregar otra base de datos guardando en otro lugar. Más adelante decimos que todo lo que también queremos ahorrar aquí en realidad sólo tenemos que hacer es primero tenemos que escribir la clase para ello como hicimos aquí que se puede cuidar de ello. Pero entonces digamos que queremos guardar esto para que no lo sé, algo así como una base de datos de Redis. Por lo que sólo vamos a añadir otra cola. Y entonces también lo vamos a mandar aquí. Y entonces podemos decir, oh, acabo de notar que aquí también hay un error tipográfico. Entonces sigamos adelante y arreglemos eso. Pero quiero decir, no hemos escrito esto por supuesto. Pero esta es una especie de idea. Todo lo que tenemos que hacer es una vez que te vayas y se va a r cubado. Entonces esta es una especie de idea que una vez tengamos la clase escrita para ello, en lugar de tener que cambiar de orden nuestra función principal y tipo de adaptar todo a eso. Es mucho más fácil de lo que podemos simplemente cambiar los archivos de configuración. Y en realidad podemos crear varios archivos de configuración diferentes para a varias canalizaciones diferentes amantes de querer correr, pero el código va a seguir siendo el mismo. Y son sólo los diferentes ductos que tenemos disponibles. O tal vez quieras proporcionar valores de entrada extra con este tipo de formatos. Espero que se pueda ver que se vuelve mucho más fácil cambiar, manipular, agregar, quitar, o incluso tener diferentes flujos. Bueno, sólo poder reutilizar el mismo código y todo lo que estamos cambiando realmente es el flujo general y las configuraciones y cosas así. Entonces, sí, sigamos adelante y retomemos esto porque por supuesto, esto no existe y no hemos implementado este tipo de clases. Pero sí, sólo una especie de más por un ejemplo que se puede ver cómo podemos extender esto y cómo se vuelve tan versátil y útil. Porque de nuevo, estamos cambiando este archivo YAML aquí y en realidad podemos crear varios archivos YAML diferentes para varias canalizaciones diferentes que queremos ejecutar. Nuestro código siempre sigue siendo el mismo. 11. Crea un lector Yaml: Muy bien, entonces ahora que tenemos definido este archivo YAML, que va a ser un ducto. En realidad vamos a seguir adelante e implementar algo que pueda leer este archivo o simplemente tomar un archivo general que asumimos tiene este tipo de estructura de trabajador de cubo. Y entonces sólo nos va a tratar el ducto. Porque nuestro trabajador de Vicki en este momento tampoco es una amenaza de sí mismo, sino como una clase que hace el trabajo y simplemente un poco devuelve los valores para nosotros. Por ahora. Yo sólo voy a comentar este de aquí afuera. Y solo podemos dejar eso en nuestra función principal por ahora y más adelante si queremos, podemos cambiar su trabajadora de refactor wiki para que en su lugar trabaje como nuestra trabajadora de Yahoo Finance o nuestra trabajadora de Postgres, donde básicamente tenemos este master hilo programador así como el propio trabajador, pero puede cuidar el trabajo para que realmente podamos pasar en estos valores y leer desde otro Q ascendente en el que luego podemos alimentar estos valores. Pero por ahora, dejemos esto tal como está, y centrémonos en implementar sí, Básicamente todo lo demás. Entonces voy a crear un nuevo archivo aquí. Y voy a llamar a éste. Simplemente llamaré a este lector de YAML. Podríamos llamarlo algo más como YAML Pipeline ejecutar o lo que sea. Está bien, y luego aquí, por ahora sólo quiero primero, e importar yaml. Eso es algo que vamos a necesitar con seguridad. Y luego sigamos adelante y solo definamos una clase y luego importamos el resto de las cosas como lo necesitamos. Entonces este va a ser nuestro Pipeline YAML. Supongo que podemos llamarlo ejecutor de tubería amarilla. Y luego vamos a seguir adelante y ejecutar el método de inicialización, que por ahora solo dejemos ese AS vacío. Nos volverás a llamar. Entonces, ¿cuáles son los otros métodos que necesitamos? Bueno, en primer lugar, necesitamos algo que realmente procese algún tipo de ducto, ¿verdad? Tenemos que poder procesar el ducto que queremos pasar aquí. Por lo que hay dos opciones para que tipo de pasar índices este ducto. Una de ellas es que lo ponemos aquí. Entonces podemos tener, conocemos el nombre del archivo o el directorio y lo encontramos aquí que podemos leer de él. O en realidad podemos inicializar el ejecutor YAML Pipeline con la tubería que queríamos ejecutar específicamente. Yo voy a elegir eso porque creo que es un poco más agradable especie de, ya sabes, decir que cada clase que tienes aquí es responsable una vez que tienes una instancia de la misma como responsable de ejecutar ese ducto. En lugar de que un ejecutor de tubería sea capaz de ejecutar cualquier ductos en, solo hace que sea un poco más fácil razonar sobre si alguna vez inicializas o si alguna vez, alguna vez tienes múltiples ductos para ejecutar, solo puedes inicializar diferentes ejecutores de canalización y tipo de nombra en consecuencia, usted uno para cada tubería, lugar de simplemente reutilizar el mismo, pero pasando en diferentes ductos más adelante. De esa manera, se puede conseguir un poco más. No confuso, pero tal vez como un poco más complicado simplemente seguirlo o no es tan obvio como podrías conseguir, hazlo si lo hizo con la inicialización. Entonces aquí sólo diré localización de ductos, que van a ser tres en ellos. O llamar nombre de archivo es porque va a ser un camino que va a estar en como ductos aquí dentro. Entonces solo quiero tener este tipo de ser justo como una ubicación general. Por lo que estableceremos este atributo. Tubería. Ubicación va a ser igual a este atributo que dijimos aquí. Escribiré una canción. Las diferentes partes de nuestro ducto es, y si también miramos nuestra función principal, está bien, Entonces, ¿qué hicimos mal? Necesidad de inicializar las indicaciones. ¿ Cuántos inicializar a los trabajadores? Y entonces tenemos que enviar hecho a las cues para. Entonces lo primero, por supuesto que nos perdimos a tus dos es que necesitamos también leer y procesar este archivo YAML, o tal vez el procesamiento ocurra más tarde, pero primero necesitamos leerlo. Entonces primer método que queremos tener este ducto de carga. Y a partir de aquí, estoy poniendo estos subrayados aquí solo porque los subrayados generalmente significan que es como un atributo o método interno a la clase. tanto que ninguno subraya métodos sobre qué tipo de y a utilizar desde el principio. Por supuesto, todavía puedes acceder a ambos en Python que este tipo de te indica que este es un método que quiero usar internamente porque no quiero a nadie más sobre el código. En realidad no quiero que llamen a la tubería de carga. Y así este tipo de indica que esto se está utilizando internamente. De igual manera aquí la ubicación de la tubería se está utilizando internamente y realmente no debería meterse con ella. Porque, ya sabes, tenemos la ubicación de la tubería definida a partir de la inicialización. Y así por supuesto, ya sabes, deberíamos cargar el ducto con el mismo archivo y eso realmente sólo debería pasar una vez. Y eso debería ser algo predefinido y establecer así. Entonces sí. Entonces tenemos que hacer aquí es que vamos a abrir nuestro jugo goo. Tantas sugerencias. Vamos a abrir nuestro archivo y cualquier variable que quieras. Y vamos a tener nuestros datos YAML sean iguales a camel dot archivo de entrada de carga segura aquí. Ahí vamos. Está bien, así que esto es algo que hicimos en nuestra última lección para solo, ya sabes, cargar aquí el archivo YAML, ponerlo en este atributo de datos YAML. Muy bien, entonces ese es en realidad el primer paso que queremos procesar nuestra sala de tuberías. Lo primero que queremos hacer es asegurarnos de que realmente cargamos este ducto n. ¿De acuerdo? Entonces ahora que tenemos este archivo YAML cargado en un objeto Python que podemos leer. Lo siguiente que queremos hacer. También, si miramos nuestra función principal, es que queremos inicializar nuestros qs. ¿ De acuerdo? Entonces vamos a tener un nuevo método. Ahí van a haber vidas iniciadas. Y son del tipo de aquí, cubos. Y sí, De esto solo queremos inicializar qs, vale, así que ahora necesitamos seguir nuestras pistas de alguna manera. Entonces voy a crear en nuestra inicialización y otro atributo que va a ser nuestro QRS. Y luego vamos a decir por nombre de cola, o en realidad dirá para Q en nuestros datos YAML. Porque entonces lo que estamos haciendo aquí es que tenemos, esto viene especie de otro diccionario. Desde entonces tenemos una llave aquí, que es porque si recuerdas, no lo es, entonces Vamos rápido, rápido echemos un vistazo a eso otra vez. Entonces vamos a importar YAML. Y entonces sólo vamos a conseguir este nombre correctamente. Cierto ensayo con ductos abiertos recortan este servidor, diría, Sí, no saldré con esta carga segura. Entonces esto es lo que vamos a tener aquí dentro. Y así en nuestra cuz podemos ver aquí tenemos esta lista y tenemos las diferentes señales con sus nombres como descripciones pulsivas. Entonces lo que vamos a hacer es que vamos a iterar sobre estas diferentes pistas que queremos. Y para cada una de estas señales realmente vamos a crear una cola. Entonces volviendo a nuestra función principal, básicamente vamos a hacer esto. Y para conseguir este Q, necesitamos importar este taco desde el multiprocesamiento. Entonces lo vamos a hacer así. Y luego por cada cola que tenemos, vamos a decir, o podemos obtener el nombre de la cola si queremos, que va a ser la Q2. Nombre. Alguna vez va a decir, los bucles son nuestro nombre de cola específico en nuestro diccionario cuz aquí solo va a ser una versión de lista inicial de la clase de cola desde el multiprocesamiento. Entonces estamos haciendo lo mismo aquí. Pero en lugar de definir estas señales así, es básicamente tenemos un objeto o un diccionario que se verá así. Por supuesto, ya sabes que los nombres que estamos usando son un poco diferentes. Pero esto es como la idea de lo que estamos haciendo. Y por supuesto, tenemos la libertad de tipo de cambiar esto porque podemos, si agregamos más señales aquí, entonces esto sólo se va a cuidar de eso. Pero realmente este es el formato que estamos consiguiendo aquí. Y en lugar de usar, y te veré en un segundo, lugar de referenciar a esta variable que contiene la Q, podemos entonces justo después sobre preferencia esa cola específica accediendo al componente del diccionario. Entonces seguimos haciendo lo mismo, pero de esta manera, nos permite en primer lugar distinguir nuestras diferentes señales porque tenemos los diferentes nombres asociados a ellos. Y también nos permite escalarlos un poco más fácilmente dinámicamente porque tenemos un objeto que puede contener un 0 indefinido. Si bien estamos escribiendo este número de código de señales que pueden subir o bajar según sea necesario. Pero sí, básicamente, ya sabes, en realidad no es nada diferente a ponerlos en una, una variable distinta. Pero no los accedemos directamente a través de la variable, sino más bien a través de una clave contenida en un diccionario. Entonces eso es lo que estamos haciendo aquí. Y por supuesto, eso es lo que queremos hacer. Lo siguiente que queremos hacer es por supuesto, inicializar las señales. Muy bien, así que hemos cargado en nuestro archivo YAML y nos hemos encargado con esta parte aquí. Entonces ahora sigamos adelante y nos ocupemos de inicializar a nuestros trabajadores. Entonces. Ese va a ser nuestro siguiente método. Vamos a inicializar a los trabajadores. Entonces vamos a decir para trabajador en datos de auto punto YAML. Y esta vez vamos a recorrer así a estos trabajadores. Y ahora queremos, bueno, en primer lugar, queremos hacer un seguimiento de cada uno de estos trabajadores. Entonces queremos saber qué trabajadores tenemos realmente disponibles o, ya sabes, ¿qué trabajadores están trabajando actualmente? Entonces vas a hacer un seguimiento de nuestros diferentes trabajadores aquí, así. Y luego, de acuerdo, así que ahora hemos llegado a un pequeño problema interesante porque estamos pasando la clase así como la ubicación de donde podemos encontrar esta clase. Pero en realidad, esto es sólo un nombre como no podemos simplemente inicializar esto. En tanto que en nuestra función principal, lo importamos específicamente. Entonces, ¿cómo podemos ir a hacer eso? Bueno, hay una biblioteca genial que podemos usar, que se llama labio de importación, que le gusta, nos permite ocuparnos de esto. Ahora, otra cosa que también notan aquí, señalando rápidamente esto es que cualquier biblioteca que esté instalada por defecto irá en la parte superior. Y luego una vez que lleguemos a las bibliotecas que son pip instalar e instalar desde una fuente externa, vamos a estar separados por una nueva línea, y éstas se van a agrupar. Y luego podemos ver en la función principal, hicimos lo mismo aquí. Por lo que este es un interno viene con Python. Entonces tenemos una nueva línea, esta biblioteca y cualquier otra cosa que sería pip install irá aquí. Y entonces tenemos una nueva línea. Y estos son todos un poco de nuestras piezas de código personalizadas que están contenidas dentro de nuestro propio repositorio aquí. Entonces de esta manera, ya sabes, somos un poco capaces de separar un poco más fácil los diferentes localizaciones tiroteos y es un poco más fácil dejar claro como lo que pertenece a qué. De nuevo, esto es más bien como una cosa visual. Por supuesto cualquier cosa que sea necesario. Simplemente lo hace un poco más limpio. Sólo quería señalarlo en caso de que te preguntes por qué estoy haciendo esto. Entonces tenemos esta importante cosa lib. Entonces por supuesto lo que necesitamos es que necesitamos la clase obrera que realmente podamos inicializar. Por lo que queremos poder leer esta clase de trabajador general para que podamos hacer algo como esto. Pero claro que no sabemos qué trabajadores vamos a conseguir porque este ducto realmente se puede definir. No obstante, ¿verdad? Al igual que eso es lo genial. Pero por supuesto, 0 notó punto izquierdo adentro desde la última vez. Eso es lo genial. Pero por supuesto, también tenemos que ser capaces de lidiar adecuadamente con eso. Entonces para hacer eso, vamos a usar la extremidad de importación o en realidad si vamos a usar primer atributo. Y te explicaré, vamos a escribir todo el asunto y luego te explicaré todo aquí en un segundo. Y vamos a hacer importar módulo de importación lib dot. Y el módulo que vamos a importar va a ser la ubicación del trabajador. Entonces vamos a acceder al trabajador específico y vamos a acceder a su ubicación específica. Y luego el atributo al que queremos acceder. Y de nuevo, sólo escribamos esto y luego repasemos una vez más. Ahí va a haber la clase obrera. Está bien. Entonces, ¿qué acabamos de hacer? Bueno, echemos un vistazo a nuestros trabajadores. Entonces echemos un vistazo a nuestro primer trabajador aquí. Entonces de verdad, ya sabes, claro que si estamos dando vueltas sobre estos trabajadores, entonces vamos a conseguir que cada uno de estos elementos aquí uno por uno. Entonces tenemos el nombre, etcétera, etcétera. este momento estamos mirando la ubicación. Este de aquí. Entonces esto nos da esta cosa de aquí, ¿verdad? Este camino trabajadores dot yahoo Trabajador de finanzas, trabajadores dot yahoo Trabajador de finanzas. Lo mismo que hicimos aquí. Trabajadores dot yahoo Trabajadores de finanzas. ¿ De acuerdo? Por lo que nuestro bucle de importación va a importar este módulo así. Entonces básicamente va a hacer algo así como la importación. Y entonces sólo va a importar, importar esto. Básicamente tipo de que nos está permitiendo hacer esto. Porque no sólo queremos todo este módulo, sino que queremos obtener una clase específica de él. Necesitamos sacar un atributo específico de esta clase. Ahora, este es un método interno de Python que básicamente nos permite acceder a atributos. En realidad funciona de la misma manera. Si tuviéramos como una clase definida específica, podríamos tomar nuestra clase aquí y, y digamos que queríamos. Contamos con nuestro horario de Yahoo Finanzas. Yo alcanzo y echando un vistazo en esto. Entonces aquí tenemos las colas de entrada. Entonces algo que podríamos hacer es que podríamos decir como Get attribute here, y luego tenemos las colas de entrada. Y así básicamente, esta es una especie de forma para que sacemos atributos de las clases, o en este caso también fuera de los módulos. Porque hacer algo como esto en realidad no funciona para clases y funciona o diccionarios, pero no funciona para clases que necesitábamos hacer, es acceder así, ¿verdad? Pero, ¿y si queremos acceder dinámicamente a una variable? Entonces no podemos simplemente como no hay buena manera que podamos tener esta sintaxis si se supone que esto es dinámico. Entonces la forma en que podemos hacer eso es mediante el uso de este método get attribute. Y, y esto dinámicamente nos permite definir el atributo que queremos tomar de esta clase así. Entonces de igual manera, podemos usar el mismo grosor, pero también funciona en este módulo de importación aquí. Entonces lo estamos importando y de ella estamos extrayendo esta clase obrera. Entonces básicamente esta cosa de aquí es lo mismo casi que hacer esto aquí, excepto que específicamente ya estamos, ya sabes, tenemos esta clase que ahora estamos tomando. Y lo tenemos específicamente en esta variable de clase de trabajador aquí para que podamos usarla y podamos inicializarla. Entonces por supuesto tenemos que hacer esos porque de nuevo, todo esto se puede definir a voluntad. Y así necesitamos poder importar realmente la clase y usarla o una inicializarla y usarla sin saber qué clase va a ser. como que necesitamos, siempre y cuando tengamos este formato de clase de ubicación, ya sabes, siempre y cuando eso se obedezca, necesitamos poder importar eso e inicializarlo. Muy bien, entonces tenemos nuestra clase de trabajador, pero también necesitamos algunas otras propiedades asociadas a ella. Cosas tan importantes si miramos a nuestros dos trabajadores aquí es que necesitamos el input q y necesitamos el QS de salida. Si miramos aquí a nuestro trabajador de Postgres, sólo necesitamos la cola de entrada. ¿ De acuerdo? Entonces vamos a simplemente leer la cola de entrada. Y ese es este atributo aquí que hemos definido con los trabajadores. Entonces vamos a decir nuestro trabajador. Y aquí lo que vamos a hacer es más que tratar de acceder al atributo directamente así. Porque en algunos casos, por ejemplo, si tenemos esto definido, esto no funcionaría porque nuestras colas de entrada realmente no se definieron aquí. Entonces para estar seguros contra algo así, en realidad vamos a usar un método dot get. Ahora, quiero mostrarles esto realmente rápido. Entonces si tenemos un diccionario, como este, diccionario muy simple, si haces x dot get a, vamos a obtener el valor de la clave a, que mapas para estar aquí. Pero si lo haces x punto get say, uno o la cuerda 1. Entonces esto está buscando la clave. Ese valor no está aquí, así que vamos a conseguir ninguno. Entonces de esta manera, en lugar de que esto falle, o bien va a obtener el valor aquí si existe o no existe, va a conseguir ninguno. ¿ De acuerdo? Entonces así podemos, ya sabes, estamos, vamos a estar seguros de que aquí no fallamos. También queremos la salida QS. Y desde aquí sólo vamos a usar este formato. Va a ser nuestra salida QS aquí. ¿ De acuerdo? Y veamos, ¿necesitamos algo más? Por lo que necesitamos nuestros valores de entrada y nuestro cubed superior. Está bien, Así que tenemos eso dentro. Pero actualmente nuestra cola de entrada aquí, en realidad va a sólo un nombre. No es la cola en sí. Por lo que necesitamos conseguir estas señales y luego podemos pasárselas a nuestros trabajadores. Entonces nos vamos a sentar a la vez, vamos a crear una nueva variable que van a ser nuestros parámetros de inicialización. Y aquí vamos a pasar la cola de entrada, que vamos a definir. Y también nos vamos a tener por ahora solo las colas de salida, que también definirán en tan solo un segundo. Está bien, entonces aquí realmente necesitamos pasar una instancia de lo lindo así, ¿no? No podemos simplemente pasar el nombre. Esto porque es sólo un nombre no es útil. Entonces para esto, tenemos aquí nuestras indicaciones. Entonces lo que queremos hacer es básicamente querer conseguir aquí esta cola de entrada. Nosotros queremos conseguirlo. Queremos obtener la instancia de cola real. Entonces vamos a decir self.users dot input, oops, y poner QM. Si pones q no es ninguno. Ninguno. Entonces, ¿cómo definimos esto? Ah, sí, claro que necesitamos la coma después. Entonces solo hay una declaración abreviada si else que podemos escribir en una línea para que no tengamos que escribirla sobre múltiples líneas. Mezclar un poco más fácil para tener eso en qué líneas, podemos tener toda esa lógica aquí directamente. Entonces si sí tenemos una cola de entrada, entonces vamos a tomar la instancia real que hemos definido aquí y usar lo que Q esté asociado a eso. De lo contrario, esto no va a ser nada. Y aquí lo que queremos hacer. Es algo similar, que va a ser, queremos. Ahora, aquí tenemos que tener cuidado porque podemos tener varios QS de salida, ¿verdad? Por lo que queremos hacer esto más como queremos hacer de esto una lista. Alguien responde a decir aquí, apagado punto-punto salida Q. Para salida Q. Y cues. Si ninguno, claro, esto es un poco largo. ¿ Voy a repasar el número recomendado de líneas? Podemos dividir esto en 2 iones simplemente poniendo aquí una baraja hacia atrás, lo que nos permite dividir esto en dos líneas. De acuerdo, entonces ahora tenemos nuestros parámetros de inicialización. Nuevamente, lo que esto hace es que nos permite romper una declaración sobre múltiples líneas sin romper la lógica. Porque si hiciéramos esto o la lógica se rompería, ¿verdad? Simplemente tenemos esta lista aquí. Y luego la siguiente línea ejecutaríamos el comunicado. Estará fuera de este año de corte atrasado. En realidad une esta lógica y básicamente dice que esta lógica continúa justo en la siguiente línea. Y de esta manera simplemente no tenemos que lidiar con este texto desbordante. De acuerdo, entonces tenemos celda Parámetros de Inicialización de nuestras instancias de trabajo aquí. Entonces, en realidad sigamos adelante e inicialicemos a nuestros trabajadores. Entonces, en primer lugar, solo quiero también querer conseguirlos o podría nombrar, por supuesto, nombre propio. Va a estar extrayendo el nombre. Entonces por cada nombre de trabajador, por ahora solo voy a crear una lista vacía para ello y luego vamos a anexar las diferentes causas de los trabajadores. Entonces por ahora, voy a decir corredores autodidactas que trabajador llamó dot append y tienen a esos trabajadores clase aquí. Y le vamos a pasar los parámetros de inicialización. Entonces esto nos permite hacer, es que toma este diccionario y básicamente convierte cada diccionario aquí en un par de valores clave que podemos pasarlo. Entonces lo que pasaría en este caso es hacer esto es lo mismo que tener algo como si nuestra entrada q aquí no es ningún looping como este. Y esto sería, por ejemplo, autodidacta cuz si tomamos, bueno, vamos, tomemos el ejemplo para el joven trabajador de las finanzas. Y yo sólo estoy adivinando aquí. Y luego repasemos lo que está pasando. Entonces esta estrella, estrella básicamente desempaqueta este diccionario y para cada clave aquí, tiene la clave aquí es esta, y luego la mapea a un valor específico en el diccionario como este. Y lo hace dinámicamente. Entonces si agregas más parámetros aquí, entonces todos estos, ya sabes, cada uno de estos se definirá en un mapeo de pares de valores clave aquí. Entonces esto es realmente bonito porque tipo de nos permite desempacar nuestros parámetros de inicialización y pasarlos individuales, como pares de valores clave aquí para que podamos definir específicamente como este es un muy peculiar sus colas de salida, por supuesto, para que esto funcione, necesitamos asegurarnos de que esos sean nombrados aquí, input q y q Así que esto ya va a ser un problema porque he llamado a esta cola de salida, pero esto se llama salida cubed aquí, así que que lo creará así. Ahora, otro problema, por supuesto, es si aquí proporcionamos parámetros que no existen. Por ejemplo, en este caso, realidad ambos tenemos entrada aquí. No tenemos una Q. superior Así que realmente si solo tenemos esto aquí, entonces se quejaría porque estamos pasando la salida Q como parámetro de inicialización. Pero no existe en el trabajador de Postgres. Pero ahí es donde estas estrella, estrella k Obras. O los argumentos de palabra clave entran. Básicamente nos permite pasar un conjunto E de argumentos de palabra clave. Entonces cualquier cosa que se defina con la palabra clave y igual a algo sin realmente tener que preocuparse, ya sabes, como las repercusiones. Simplemente se lo toma y luego podemos hacer con él lo que queremos si queremos usarlo. En este caso, simplemente lo pasamos a la clase de hilo a padre. Pero también podríamos simplemente ignorar por completo esto y no hacer nada con él. Hola. Esta es una manera realmente bonita de hacer fuera porque podemos simplemente desempacar este diccionario y de inmediato, ya sabes, pasarlo aquí. Y sí, así que casi tenemos la lógica que tenemos aquí. Todavía faltan algunas cosas. Por ejemplo, aquí estamos definiendo el número de trabajadores que actualmente no tenemos. Esa es una solución fácil para nosotros porque sólo podemos entrar aquí. Y podemos decir, por ejemplo, instancias. Digamos que queremos forma. Y yo tomaré lo mismo y lo pondré por aquí. Este no tiene que ser el mismo orden. De nuevo, estamos obteniendo un mapeo de diccionario a partir de esto. Es sólo el momento conveniente para ser el mismo orden. Y aquí podemos decir, o Digamos que queremos muchos trabajadores de Postgres, pero no queremos que tantos lavadores. Entonces ahora podemos decir que número de instancias que queremos es solo obtener los atributos de instancias de aquí, así, y luego más bien simplemente inicializarlo una vez vamos a decir que en rango el número de instancias. Y queremos crear trabajadores de Domini. Aquí. En realidad, probablemente sería mejor para nosotros hacer algo como esto. Y en realidad también podemos hacer es poner un parámetro por defecto o un parámetro de retroceso. Entonces en este caso, si volvemos a este x punto punto a, obtenemos el valor b que está asociado al k aquí. Si lo hacemos x punto punto querido existir. Pero si hacemos esto, eso significa que si no existe, entonces volvemos por defecto a esto. Entonces si por alguna razón las instancias con las que no está definida, sabemos que queremos trabajar para esto porque está en la tubería. Entonces sólo vamos a usar uno. De lo contrario si las instancias artefacto y vamos a usar eso. Y así de esta manera, ahora podemos aumentar dinámicamente si queríamos o disminuir cada vez que queramos el número de trabajadores aquí dentro, y simplemente crearemos a esos muchos trabajadores. Y entonces lo último que queremos hacer es, claro que queremos llamar a este método auto punto inicializar a los trabajadores. Y entonces también queremos poder sumarnos a los trabajadores como tenemos aquí. Entonces trabajadores y ya dijimos por trabajador en, los trabajadores dirán por deformar nombre y trabajadores y luego diremos por hilo obrero. Entonces recuerda que tenemos un, este es un diccionario y la cada clave aquí es el nombre del trabajador. Y luego con cada valor vamos a tener una lista. Y cada una de estas listas será una clase obrera. Por lo que cada uno de estos será un hilo en ejecución. Por lo que queremos recorrer cada hilo. Y entonces aquí llamaríamos al punto unirse así. Está bien, así que esta va a ser la clase. Y vamos a parar aquí por ahora porque estamos obviamente esta clase está implementada en cualquier parte todavía, pero esto va a ser una especie de, esto forma la base de su clase que nos permite hacer todas estas cosas. Por lo que las siguientes lecciones vamos a implementar esta clase y tipo de pasarla a nuestra función principal y, ya sabes, funcionalidad por ahí. Vamos a hacer cualquier depuración, por supuesto, porque no hemos sido capaces de probar esta clase en absoluto, bien, ahora sólo está un poco escrito así. Por lo que probablemente es probable que haya algunos errores aquí dentro que vamos a necesitar arreglar. Algunos también hacen eso y luego tipo de hacerse cargo de eso. Y tal vez entonces también cambiar un poco una funcionalidad para que realmente podamos tener a nuestro trabajador wiki aquí también sea algo que podamos definir cómo específicamente queremos poder pasar tal vez en múltiples URL. Sí, Pero sí, supongo que los haremos en las siguientes lecciones, ya que ya no quieres arrastrarnos por mucho tiempo aquí. 12. Mejora nuestro Wiki Worker: Muy bien, entonces ahora que tenemos este YAML vamos a buscar. En realidad sigamos adelante e implementemos esto en nuestra clase principal porque ahora mismo estamos en nuestra función principal porque en este momento sólo tenemos este costo bien, pero en realidad no estamos haciendo mucho con él. Y aún no es perfecto como veremos en un segundo. Pero vamos a decir desde M rigor, vamos a importar el ejecutor YAML Pipeline. Muy bien, entonces vamos a tener nuestro ejecutor de Pipeline YAML sea igual a. Y ahora necesitamos definir la ubicación del gasoducto. Por lo que nuestra ubicación de ductos a partir de ahora va a ser pipeline slash wiki, punto de tubería de cobre Yahoo YAML. Ahora esto es lo suficientemente codificado. Idealmente moverá esto a variables de entorno, pero lo haremos más adelante. Vamos a hacer que esto funcione por ahora. De acuerdo, así que esto ya no necesitamos porque tenemos a nuestro ejecutor YAML Pipeline o trabajadores wiki. Interesante, porque aún necesitamos eso. Esto ya no lo necesitamos. Y esto también ya no necesitamos. Entonces necesitamos cambiar un poco nuestro ducto de procesamiento porque no podemos, veremos en un segundo, pero en realidad no podemos unirnos todavía a los trabajadores. Porque ahora mismo hay algo así de fortuito. No fortuito, pero como si fuera un poco aún no perfecto porque tenemos algunas cosas dentro del YAML y ejecutarla y algunas cosas como veremos en un segundo todavía sin ella. Entonces si en realidad solo llamamos a tubería de proceso aquí, vamos a cargar el ducto. Vamos a inicializar un QRS y trabajadores. No queremos unirnos a ella porque si hacemos eso, entonces, ya sabes, yo soy básicamente todos los trabajadores estaban un poco terminados y entonces no hemos metido nada aún, pero no podemos meter nada aún porque las q solo se inicializan una vez que en realidad inicializar la cola y el paso de la tubería de proceso aquí. Entonces desafortunadamente, por ahora, lo arreglaremos más tarde, pero por ahora vamos a tener que apagar este porro por aquí y vamos a tener que llamarlo manualmente más adelante. No estamos manualmente, vamos a subir a solo llamarlo más tarde. Entonces tenemos nuestro símbolo Q. Ahora, la Q que queremos. Por ahora sólo los voy a usar. Valor codificado duro va a ser este símbolo Q aquí. Y por supuesto, ahora queremos hacer todo tipo de este YAML Pipeline, creo aquí. Entonces, pero por ahora solo probemos la funcionalidad. Entonces vas a entrar a nuestro ejecutor de ductos YAML. En realidad vamos a acceder a este atributo. Y aquí vamos a acceder al, el símbolo Q, porque ahí es donde se necesita escribir esto. Entonces esa es la clave en la que queremos escribir, por supuesto, sintaxis no ideal. Pero debido a que nuestro trabajador wiki en realidad no está definido la tubería y dentro del uréter un poco tienen que hacerlo así por ahora. Está bien. Después la impresión realizada después. Por lo que actualmente también tenemos que hacer esto. Um, así que por ahora, nosotros, porque ahora podemos definir como el número de diferentes instancias aquí por nosotros mismos. Simplemente vamos a llevarnos alguna gorra superior grande. Y vamos a decir, en lugar de, ya sabes, específicamente decir algún número, sólo vamos a decir 20 fotogramas. Pero por supuesto esto tampoco es ideal. Pero, ya sabes, vamos a que esto sea así por ahora. Vamos a poner hecho al símbolo q. Y aquí donde se están uniendo los hilos, así sucesivamente. Está bien. Por lo que ahora tenemos que unirnos a nuestras amenazas y mostrar alguna otra sintaxis, try y trabajadores. Vamos a asegurarnos de que te unas a los acechadores, ¿de acuerdo? Está bien, así que sigamos adelante y ejecutemos esto y veamos si funciona. Probablemente bugs que tenemos que arreglar. Muy bien, entonces nuestro trabajador de Postgres obtuvo una inesperada salida de argumento de palabra clave Q. Así que echemos un vistazo a eso. Trabajador de Postgres aquí. Consiguió un inesperado verdadero. ¿ Dónde está nuestro tema? Trabajadores inicializados, clase obrera. De acuerdo, Entonces piensa que el problema es que estás haciendo programador maestro Postgres. No, ese no es el problema. Postgres maestro. Y obtuvo inesperada salida de argumento de palabra clave Q. Así que mirando nuestro log aquí, parece que esto se está quejando tan pronto como hacemos la super inicialización. Entonces tal vez o la nube de subprocesos es, la clase de subprocesos se está quejando de esos. Entonces vamos a probar eso. Vamos a entrar a Python. Vamos a importar. Escribiendo, vamos a decir enhebrando hilo de punto. Y vamos a probar la salida Q es igual a. Así que ahí es donde está el problema. Entonces vamos a confiar, poner esta salida Q aquí, para que no lo pasemos a los argumentos de palabra clave aquí. Alternativamente, también puedes hacer es que podemos eliminarlo de este diccionario usando esta llamada pop, que solo la va a eliminar y en realidad como que nos da el valor aquí, pero solo lo va a eliminar de los argumentos de palabra clave. Entonces, y aquí probablemente queremos tener algo de seguridad. Quieres decir si salida Q y argumentos de palabra clave, entonces queríamos simplemente eliminarlo. Entonces intentemos correr ese tiempo mujer. Está bien. Hasta el momento no enfermeras, probablemente buena señal. Está bien. Entonces llegamos a algún tipo de tiempo de espera que está bien. Pero parece que terminó. Por lo que tuvimos algún tipo de tiempo extendido por la razón que sea por ahora. Pero claro, esta vez vengo de aquí. Tan joven. Aparte de eso, parece que está funcionando. Entonces eso en realidad es bastante genial. Eso significa que podemos tomar este código y podemos ver qué queda y qué más hay que implementar. Está bien, así que claro, una de las cosas que queremos mover es todo esto no es muy bonito, ¿verdad? Al igual que idealmente, tendremos al trabajador wiki. Y todo este proceso en el que mantenemos los valores de los trabajadores se están alimentando. Y todo eso se está haciendo en este tocón de tubería de proceso. Y de esa manera tampoco tenemos que llamarlos unirse y recurrirse aquí abajo. Entonces, ¿cómo vamos a seguir haciendo esto? Entonces la mejor manera que o no, creo que la forma que más me gustaría es que nos extiendan a este trabajador wiki. Y básicamente lo que vamos a tener como ser querer tener un tipo similar de opción donde tengamos esta masterclass para la que podamos aportar valores. Y a partir de estos valores, entonces vamos a tener, ya sabes, instancias de trabajador wiki o simplemente una sola instancia de trabajador Wiki, tal vez eso se vaya a hacer cargo de eso. Entonces lo que podemos hacer es que podemos tener un programador maestro de trabajo wiki. Y también vamos a tener en realidad que esto sea una instancia de hilo de punto de enhebrado. Ya está en crédito para nosotros. Agradable. Entonces la razón de esto es porque en nuestro lector YAML, realidad vamos a llamar al método join. Y de lo contrario, de esta manera Obtenemos como una bonita llamada del método join porque viene heredado de la clase de hilo. Pero de lo contrario necesitábamos definirlo nosotros mismos para que cuando lo llamamos unirse, ya sabes, no se rompa. Y hasta podrías hacer eso solo haciendo algo como esto. Simplemente lo pone a disposición. Ya sabes, si, si no vino heredado de la clase padre, solo para que no se rompa en este paso para que podamos seguir ese mismo tipo de orden lógico. Pero hagámoslo en realidad un amenazado y sigamos adelante e inicialicemos el padre. Aquí vamos a tomar argumentos de palabras clave. Nuevamente, paso frecuente al padre de enhebrado. Sí. Fin. A qué queremos en nuestra trabajadora Vicki aquí llamó una de las cosas que queremos hacer. Por supuesto, no puedo olvidar si quieres iniciarlo. Y entonces también tenemos que tener cuota unclass aquí. Y vamos a hacer algo, ya sabes, mientras sea lo que sea esto es cierto. ¿ De acuerdo? Entonces, ¿qué queremos en nuestro programador maestro Mickey? Entonces si echamos un vistazo atrás a nuestra función principal aquí, queremos que nuestro trabajador básicamente sea capaz de tal vez tomar diferentes URL de entrada, crear un trabajador wiki con cada URL, y luego tener a ese trabajador wiki como pasar por su proceso al conseguir los símbolos y simplemente ponerlos en una salida Q. Entonces lo que necesitamos para esto de lo que necesitamos si la salida Q. Y a partir de aquí, queremos asegurarnos de que no pases la cola de entrada porque eso va a obtener la misma queja. Entonces vamos a decir si nuestra entrada q está en nuestros argumentos de palabras clave, simplemente lo eliminamos y simplemente saltamos de eso. Y otra cosa que queremos sin embargo, es en realidad queremos algún tipo de entradas que podamos pasar, ¿verdad? Al igual que no tenemos una cola de entrada porque no íbamos a estar leyendo desde una cola de entrada, pero sí queremos entradas que podamos iterar. Entonces vamos a decir, vamos a asumir que vamos a estar pasando y las entradas van a decir entradas. Y por supuesto tampoco queremos pasar entradas. Por lo que entradas espacio para tomar desde aquí. Y vamos a volver a salir así. Está bien, así que sí, así que este es el formato que queremos. Por supuesto, también queremos establecer realmente la salida Q al acusado. Y en realidad usemos la misma sintaxis que estamos usando aquí. Para que podamos establecer QS de salida múltiple si procede. Pensado de la manera que podamos, si volvemos a aquí, esa manera, cada vez que obtenemos valores , si queremos, podemos ponerlos en diferentes colas de salida para que, ya sabes, diferentes trabajadores upstream puedan utilizarlos para cualquier propósito. Usando eso para, está bien, Si Q2 y está bien, así que ahora necesitamos definir estas entradas y también vamos a cambiar nuestro método de ejecución aquí. Entonces en lugar de decir si bien cierto, vamos a decir para entrada y aventurarse es porque ahora en realidad tenemos un número limitado de entradas que esperan que queremos repasar esto. Y yo soy suma de rango. Actualicemos nuestro archivo YAML para que queramos que se produzca nuestra wiki. Y en lugar de inicializar brazo freaky Bucher, queremos inicializar el programador maestro de trabajo wiki. Hemos llamado a estos valores de entrada. Entonces si quieres, podemos actualizar desde entradas aquí dos valores de entrada. Eso está totalmente bien. El punto es que tengo que asegurarme de que por supuesto, también hagamos esto aquí. ¿ De acuerdo? Por lo que queremos tomar valores de entrada aquí. Y luego para cada valor de entrada como este, queremos iterar sobre estos. Y para cada uno de estos valores de entrada, solo queremos poner estos valores en el símbolo de salida Q aquí. Muy bien, entonces tenemos nuestras entradas aquí. Entonces para cada entrada, luego vamos a tener en nuestro Wiki Corker, queremos inicializar esto. En realidad queremos inicializarlo con una URL específica. Entonces lo que vamos a hacer es mover la URL a los parámetros de inicialización aquí. Y de esa forma podemos inicializarlo directamente para las diferentes entradas que vamos a proporcionar a través de aquí. Y ahora, también necesitamos, bueno, si volvemos a nuestra función principal, podemos iterar sobre los diferentes símbolos y luego queremos poner esos en nuestra salida Q. Así que por ahora solo podemos tomar esta lógica usando el símbolo contador a eso. El único motivo por el que estamos usando esto es de nuevo, recuerda, para que no pongamos todos los símbolos en la salida Q para que estemos desguazando todos estos valores diferentes, aplíquelos en Postgres. Y, sino más bien solo hacemos los primeros cinco solo para asegurarnos de que esté funcionando. No necesitamos hacer como los 500 ahora mismo. Entonces nos vamos a hacer cargo de este hospedaje y vamos a tener, soy mayor. Voy a decir cuatro fuera, poner q en nuestras colas de salida. Entonces para cada salida Q, Uops, No, queremos asegurarnos de poner ese símbolo ahí dentro. ¿ Verdad? Entonces vamos a repasar esta lógica aquí. Por lo que tenemos nuestro programador maestro de trabajo wiki, que va a ser una instancia de la clase de hilo. Para esto, vamos a tomar argumentos de palabra clave y salida Q. Y si no tenemos entrada q y queremos asegurarnos de que eso se elimine para que no lo pasemos a la inicialización de la clase padre de subprocesos. También queremos valores de entrada, y estos valores de entrada van a ser diferentes URL que podemos definir aquí así. Y por supuesto, para nuestra salida cuz queremos asegurarnos de que tenemos la opción de tener diferentes tacos alfa para que podamos tener aquí, por ejemplo, como símbolo Q2 y como segundo símbolo Q. Y si tenemos esto, déjame también por supuesto necesito definirlo aquí arriba, pero, ya sabes, solo si queremos poner esto a más de una Q, así que soy más de un tipo diferente de trabajador puede consumir este downstream que tenemos esa opción. Muy bien, queremos asegurarnos de que inicializamos un hilo padre. Y luego queremos iniciar el proceso, igual que hacemos aquí. Ahora, para que esto funcione, también necesitamos el método de ejecución, que se va a llamar Kind of cual se puede cuidar automáticamente para nosotros porque estamos lanzando padre. Pero diferente a nuestros trabajadores aguas abajo que van a estar esperando valores hasta que salga del QRS y los lea. Diferente a eso. No estamos leyendo desde un agudo aquí, pero estamos leyendo desde un conjunto predefinido de entradas. Entonces sí, sólo queremos asegurarnos que estábamos pasando por el conjunto predefinido de entradas que tenemos aquí, porque ya sabemos cuáles son estos valores. Entonces no necesitamos, ya sabes, tratar de sacarlos de algún tipo de lindo. Entonces vamos a repasar las diferentes URL de entrada. Por cada entrada, vas a crear un trabajador wiki. Este trabajador wiki va a cuidar el desguace, por lo que encontrando cada uno de los símbolos. Entonces vamos a tener esa misma lógica aquí. Y por cada símbolo que obtenemos, queremos ponerlo a la salida QS, ya que podemos tener múltiples jóvenes olímpicos, queremos asegurarnos de que pasemos por encima de cada Q. superior Y luego estas cosas aquí, esto es realmente solo para que no desguace 500 símbolos, sino que solo hagamos los primeros cinco solo para que vaya un poco más rápido. Muy bien, entonces tomemos esta salida y al final. Por lo que esta también es lógica que queremos movernos realmente a nuestro trabajador quickie. Y al final aquí, quiero decir para la salida Q y los tacos superiores. Y luego aquí otra vez, sólo vamos a decir como un número ridículo en este momento. 20. Queríamos asegurarnos de que enviamos. Y sólo queremos que esto suceda después de que, ya sabes, se hayan enviado todos los símbolos. Y luego una vez que todo eso termine, en realidad podemos enviar hecho. Entonces ya no necesitamos esto aquí. no necesitamos que se unan a los trabajadores porque ya lo podemos hacer. Y aquí. Y yo escribiré, y echemos un vistazo a eso. Está bien, así que vamos a seguir adelante y tratar conocido, a ver qué pasa. A ver si nos perdimos algo. ¿ Verdad? Por lo que está buscando valores de entrada 0, 0, curso, y nuestro lector amarillo. También necesitamos asegurarnos de que pasemos escuchar. Por lo que los valores de entrada son iguales al punto de trabajador. Sin embargo, los valores de entrada. En realidad voy a hacer esto aquí abajo. Y voy a decir, si uso no es una anomalía, entonces quiero ponerlos en los parámetros de inicialización. El motivo por el que estoy haciendo esto, en lugar de proporcionar siempre la media y los parámetros de inicialización, como lo hacemos aquí arriba, es porque nuestros valores de entrada son como un caso especial, específicamente para nuestro trabajo wiki aquí, ¿verdad? Porque en todo el otro trabajador está ahí va a estar ingresando acusado, tal vez no los acusados con van a ser genuinamente como colas de entrada y salida. Pero nuestros valores de entrada realmente sólo van a ser específicos de nuestro único trabajador aquí. Entonces, en lugar de ponerlo aquí y luego entrar el uno al otro trabajador y asegurarse de que esta cola de entrada, estos valores de entrada no se pasan como argumentos de palabra clave hasta el hilo, como la inicialización de subprocesos aquí. Sólo voy a pasarlo si en realidad está ahí dentro y de esa manera sólo necesito cuidarlo por aquí. De acuerdo, así que intentemos eso otra vez. No hay error hasta el momento, lo cual generalmente es una buena señal. Pero esperemos y veamos qué pasa. Está bien. Enfriar. Entonces parece que las cosas están funcionando. Y sí, tenemos a nuestro trabajador wiki ahora que, sabes, está tomando todos estos valores. Pero claro para asegurarnos de que las cosas estén funcionando, Vamos a seguir adelante e imprimir en nuestro trabajador de Postgres recibió esto solo para ver si llega hasta el final, todo el camino abajo corriente. Está bien, entonces está recibiendo valores. Entonces todo está funcionando, lo cual es impresionante. Hay, por supuesto, todavía una cosa que no está funcionando, que es que no está recibiendo hecho correctamente todo el tiempo y no es como probablemente estallar. Y la razón de esto, si entráramos al trabajador de Yahoo Finanzas, es en realidad sólo se está poniendo hecho aquí. Y así el problema aquí en este caso es, si vamos aquí, tenemos dos instancias, pero aquí tenemos seis instancias. Por lo que notarás que la diferencia, seis menos dos son cuatro. Tenemos cuatro instancias que no están recibiendo, que se hacen señal ahora mismo. Entonces lo que podemos hacer por ahora es solo sacarle esto porque se están escapando. Y vamos a decir aquí, para alfa q y arriba accuse ticket sólo dirá para mí en el rango 20. Por cada salida Q, sólo vamos a mandar un montón de ellos. Por supuesto, esto no es ideal porque si tenemos 21 trabajadores y mucho del mismo problema, pero por ahora, ya sabes, debería estar bien. Por lo que podemos simplemente volver a ejecutar eso rápidamente. Otra cosa que también notarás es que aquí no definió instancias. Y de esa manera se puede ver eso, genial, y todo funcionó bien porque no definimos como las instancias aquí. Esto se encargó de eso. Ahora este es otro pequeño tipo de matiz que tenemos porque aquí realmente no queremos varias instancias. Porque si vamos a tener varias instancias, no van a estar consumiendo de la misma cola, sino que en cambio van a estar repitiendo este proceso. Entonces aquí en realidad no queremos varias instancias porque si lo hacemos, como dije, no están consumiendo de una cola. Por lo que no están bajando un taco y dividiendo la obra. Van a estar repitiendo el trabajo porque la forma en que funciona esto es que en realidad va a iterar sobre este conjunto de valores de entrada. Entonces aquí tenemos que tener cuidado de que solo tengamos 11 instancia. Por lo que podemos salir, por ejemplo, a nota, sólo tener una instancia aquí. De lo contrario, desechamos este símbolo. Entonces por supuesto, ya sabes que hay diferentes formas de hacer esto. Una cosa que podríamos hacer es que podríamos otra vez como un separado esto fuera y ya sabes, sólo tener nuestro propio trabajador wiki consumido de una cola. Y alimentamos estos valores de entrada en q mismo. Pero en algún momento, ya sabes, necesitamos, ¿necesitas llegar al punto en el que o tenemos un trabajador que solo tiene una instancia que simplemente alimenta todos estos valores de entrada a una cola de la que el trabajador wiki podría entonces consumir. Entonces por ejemplo, podríamos tener como otro trabajador aquí, sólo va a ser, ya sabes, URL cedro. Y este de aquí puede tomar como éste de aquí podría tomar estos valores de entrada. Y luego las colas de salida. Las colas podrían, por ejemplo, ser salidas URL. Y luego aquí y poner Q, podemos leer desde aquí. Y en este caso, como este trabajador va a ser el que sólo puede tener una instancia. Y tal vez lo sea, ya sabes. Entonces como este problema va a ser como extendido hacia adelante, hacia arriba. Pero en este caso, podemos tener múltiples hilos aquí porque ya no van a estar leyendo a partir de valores de entrada, sino que van a estar creando a partir de la cola de entrada. Um, así que si quieres, en realidad puedes jugar con eso e implementar eso para que realmente podamos desechar diferente Reino Unido o bien al mismo tiempo si tenemos más de una instancia aquí. Pero sí, claro, en algún momento nos vamos a estar topando con este tema en el que sólo necesitamos proporcionar algún tipo de semilla. Y si tenemos más de una instancia proporcionándoles la dirección c e iniciando duplicados. Entonces sí, ya sabes, solo ten en cuenta eso, ese problema sólo existe. Y así podemos dejar una nota, por ejemplo, para decir como sólo tener una instancia aquí. Y hasta podemos dejar esto claro de nuevo, podemos decir instancia uno y podemos decir, Por favor, no nos cambies. De lo contrario, hacemos trabajo duplicado, algo así. Nos vemos nota arriba. Y ejecutamos esto una vez más solo para asegurarnos de que está funcionando bien y poner q este no existe. Y si todo está funcionando correctamente, pero, ya sabes, sólo un poco de estar al tanto de eso. No queremos tener más de una instancia aquí porque estamos iterando sobre estos como valores de entrada definidos manualmente aquí. Pero está listo por un minuto. Sí, Mirando nuestro resultado y mirando nuestra función principal, las cosas en realidad se ven bastante geniales. La única otra cosa que podemos hacer, por supuesto, es si queremos obtener el tiempo de ejecución adecuado. Y ponemos eso en la parte superior aquí porque de lo contrario probablemente iniciando este tiempo de cobre después de esto, pero estamos llamando a unirse a los trabajadores aquí. Por lo que sólo vamos a estar iniciando esto una vez que todo el trabajo esté hecho. Entonces si quieres conseguir el tiempo adecuado, y por supuesto tenemos que poner esto arriba así. Y también podemos quitar todas estas importaciones no utilizadas aquí porque ahora todas estas importaciones han sido trasladadas a nuestro lector amarillo. Podemos simplemente ahorrar y rumores o más tiempo para asegurarnos de que esto funcione correctamente. Pero ahora esto es realmente bonito porque mira lo pequeña que se ha vuelto nuestra función principal. Se ha vuelto tan simple. Simplemente tenemos el ducto que queremos correr. Y entonces sólo tenemos nuestro ducto ejecutar o que se encarga de todo. Y ahora si queremos hacer más trabajo, entonces, ya sabes, podemos extender esto. Podemos tampoco, si tenemos más URLs que es seguir la misma estructura que creemos que nuestro trabajador wiki puede cuidar. Entonces ya sabes, podemos poner aquí más valores de entrada. Podemos extender esto para tener perspectivas diferentes. Por lo general, antes hablábamos de tal vez guardar dos bases de datos diferentes o algo así. Y por supuesto, ya sabes, si creamos un trabajador extra, necesitamos asegurarnos de que definimos también a ese trabajador. Pero realmente todo el arduo trabajo ha sido transferido al lector amarillo. Esta cosa en realidad se ocupa dinámicamente justo de este archivo de configuración YAML aquí. Entonces realmente como podemos extender esto tanto como nos guste. Por supuesto, como lo único que tenemos que hacer si agregamos un tipo diferente de trabajador, necesitamos asegurarnos de que, ya sabes, definamos la clase de trabajador y todo así y asegurarnos de que eso funcione correctamente. Pero una vez que tengamos disponible esa clase obrera, podemos reutilizarla. Podemos extender nuestros ductos, ¿verdad? Diferentes ductos. Hay un montón de cosas geniales que podemos hacer y todo lo que podemos definir sobre esos archivos YAML bastante legibles y fáciles de mantener. Por lo que es tan fácil para nosotros escalar y bajar el número de diferentes trabajadores que queremos tener. Si vemos, por ejemplo, o a nuestros trabajadores de Postgres un cuello de botella. Porque realmente todo es sólo una especie de espera para ser guardado en Postgres puede aumentar el número de instancias. O si le va bien, en realidad podemos dejarlo tal como está, o incluso disminuir el número de hilo no es muchos. Queremos escalar el número de raspadores que tenemos. Entonces hay tanta libertad para nosotros para sintonizar nuestros ductos aquí. Y todo esto se ha trasladado a este archivo YAML y a nuestro código de plata, sólo nos encargaremos dinámicamente de todo esto. 13. Mejora todos los trabajadores y agrega la supervisión: Muy bien, entonces en este paso, vamos a limpiar nuestro arte YAML Pipeline ejecuta o un poco más, solo mirando nuestra función principal aquí, realmente lo que estamos haciendo es llamar a este paso de proceso de tubería, donde hacemos todo desde como cargar el ducto y luego inicializarlos como colas y trabajadores. Y luego por supuesto llamando aquí a este conjunto para que, ya sabes, esperemos a que terminen todos estos trabajadores. Y si sólo miramos la forma en que, Vamos a ver en nuestro wiki trabajador por ejemplo aquí. Entonces la forma en que estamos manejando el envío hecho en este momento no es ideal. Porque realmente lo que estamos haciendo es que solo estamos enviando esto, digamos, 20 veces. Lo cual es, bueno, es un poco raro porque imagina que tenemos varios de estos trabajadores corriendo al mismo tiempo. Entonces en este caso, si vamos a estar enviando hecho, pero uno de los otros trabajadores en realidad no está hecho. Y estamos enviando hecho más de lo que tenemos ese número de trabajadores río abajo, entonces en realidad todos van a estar leyendo hecho y van a estar parando. A pesar de tal vez algún otro trabajador, ya sabes, aún poniendo valores en esa cola más adelante. Ahora por supuesto, en este caso, bueno, podemos tener eso para el trabajador de Yahoo Finanzas, por ejemplo, para el wiki el trabajo actualmente no son tanto porque estamos como limitando las instancias aquí a una. Ya que necesitamos asegurarnos de que básicamente proporcionamos esta semilla no duplicados. Pero esto no puede suceder con el trabajador de Yahoo Finanzas. Si uno de ellos termina justo antes que el otro, y simplemente pone todo ahí dentro y entonces el otro en realidad sigue funcionando y poniendo algunos para su uso mientras entonces todos los trabajadores de aguas abajo van a estar leyendo esto y en realidad no van a estar consiguiendo los valores finales que no están en este cubo. Entonces en este paso, optimizemos un poco esto. Y tomemos esto enviando la señal de nuestros trabajadores y la vamos a trasladar a nuestro principal trabajador. Esencialmente, sólo que actualmente no somos un trabajador, es sólo una especie de clase que nos ayuda a ejecutar el ducto. Pero en realidad vamos a importar threading. Y vamos a hacer de esto un hilo 2. Entonces lo vamos a hacer básicamente nuestro principal trabajador. Y aquí lo que vamos a hacer ahora es que estamos, bueno, claro que necesitamos agregar el paso de ejecución. Aquí. Nos vamos a cuidar de monitorear el progreso y enviar comandos hechos una vez que todo esté hecho. Por lo que también vamos a estar quitando que se unan a Trabajadores. Porque el primer paso que vamos a estar haciendo una vez que se inicie este proceso es que en realidad vamos a estar mientras se ejecuta el paso del proceso de tubería. Y así si aquí nos hemos sumado a los trabajadores, entonces básicamente todo va a quedar bloqueado hasta que lleguemos a este punto. Entonces por supuesto, no podemos llamar a los trabajadores de unirse y en realidad ni siquiera lo necesitamos porque también aquí vamos a tener como un bucle infinito que básicamente solo va a cuidar de todo, puede hacerse cargo de todo el monitoreo, etc, pared, todo lo demás está activo. Y para esto entonces por supuesto también tenemos que empezar nuestro hilo para que, ya sabes, empiece a correr. De acuerdo, entonces, ¿qué vamos a hacer aquí? Bueno, realmente lo que queremos hacer es querer saber por cada trabajador, primer lugar, cuántos, como lo q está enviando a dos, y también cuántos trabajadores siguen vivos. Y entonces lo que queremos poder hacer es una vez que todos los trabajadores ya no estén vivos, queremos enviar hecho a todas las colas de salida a las que envía. Entonces, por ejemplo, si tenemos tres QS de salida aquí y éste está hecho, entonces queremos enviar hecho a todas estas colas de salida. E idealmente, el número de veces que enviamos hecho también depende de cuántas instancias estén consumiendo realmente de esa cola. Entonces vamos a tener algo separado que solo nos ayude a rastrear cuántas instancias son, cuántos trabajadores están consumiendo de cada cola. Entonces sigamos adelante y pongamos eso. Y en realidad vamos a hacer que esta parte de nuestros trabajadores de inicialización. Pero primero realmente vamos a poner esto en nuestro método inicializado de función inicializada aquí. Voy a escribir algunas de las cosas y como explicar qué pasaba con ellas. Podemos recapitular de nuevo una vez que esté fuera, porque una vez que lo tengamos escrito, obviamente será un poco más fácil entender la lógica en lugar explicarla en un sentido más abstracto. Entonces vamos a tener aquí consumidores de Cubo. Y también vamos a anotar las indicaciones aguas abajo. Por lo que la variable Q consumidores básicamente va a decir, para este símbolo Q, esto es cuántos trabajadores están consumiendo de esta cola. Y el cuz aguas abajo básicamente siempre va a ser el trabajador y qué cuz tiene sentido también. Entonces estos son los dos atributos extra que estamos agregando aquí para que podamos hacer un seguimiento de esta información porque la vamos a necesitar más adelante. Entonces ahora cuando estamos inicializando a nuestros trabajadores, tenemos que hacer un seguimiento de, bueno, primer lugar, ¿qué señales hace bien? Dos. Por lo que tenemos la salida QS. Seguro. Aquí. Entonces vamos a tener, vamos a sumar aquí en nuestras cues aguas abajo. Para este trabajador va a estar escribiendo dos colas de salida de yeas. Ahora note estamos tomando los nombres de la salida QS aquí para que podamos referirlos más adelante aquí. Pero en realidad no necesitamos tomar la instancia de la cola. Podemos simplemente rastrear el nombre aquí. Y entonces también queremos saber qué se está consumiendo Q. Entonces si sí tenemos una cola de entrada aquí, y entonces podemos decir, si input q no es ninguno, entonces queremos señalar aquí esta Q como siendo consumida por estos muchos trabajadores, ¿verdad? Entonces dependiendo del número de instancias que tengamos aquí, y eso es cuántos trabajadores van a ser consumidos de la cola. Ahora, con esto, como que tenemos una suposición implícita de que cada cola es una especie de va a ser para un trabajador. Entonces, por ejemplo, si tenemos un segundo trabajador que quiere hacer uso de los resultados desde aquí, no va a estar leyendo desde esta cola porque eso básicamente es difundir nuestros valores sobre dos trabajadores separados que van a ser haciendo dos cosas separadas. Si quieres almacenar estos datos sin procesar en algún lugar, entonces tenemos que tener una salida Q separada, que no nos perdamos ningún valor que básicamente los dos trabajadores, uno de ellos va a ser el procesamiento y el otro eso sólo va a estar almacenando los valores brutos. No quieren leer desde el mismo cubo porque entonces son como compartir los datos y una de las partes del mismo se están guardando y otras partes de ser procesadas. Pero realmente queremos que cada, cada paso en esta tubería procese todo el conjunto de datos. Entonces si necesitamos este conjunto de datos 2, entonces necesitamos agregar otra Q de salida aquí para asegurarnos de que podemos usar el conjunto de datos completo. Y así con esto y lo que estamos escribiendo aquí, de nuevo, estamos asumiendo que Cada cu es específico de un trabajador. Entonces si estamos consumiendo del símbolo Q aquí, entonces no podemos consumir del símbolo Q con un trabajador separado en otro lugar, porque de lo contrario, van a estar dividiendo los datos aquí porque todos lo van a estar tomando fuera. Entonces esa es una especie de suposición implícita que estamos haciendo aquí. ¿ De acuerdo? Pero ahora tenemos, ya sabes, ahora sabemos a qué trabajador le está escribiendo Q cada trabajador, y también qué q, cuántos trabajadores están consumiendo de cada cola. Muy bien, entonces tenemos el proceso de Ejecutar aquí. Entonces ahora lo que queremos hacer es básicamente, y podemos establecer esto en un intervalo. Por lo que también voy a importar tiempo porque esto nos permite tener una función de sueño al final. Entonces tal vez dormimos cinco segundos al final. Para que no nos guste hacer esto continuamente, sino básicamente hacerlo a intervalos. Entonces aquí vamos a estar haciendo nuestro monitoreo. Entonces lo que queremos hacer es básicamente por cada trabajador y por cada hilo y cada trabajador, solo queremos comprobar es que sigue funcionando. Um, entonces, ¿qué significa eso? Si miramos a nuestro trabajador de Yahoo Finanzas, por ejemplo, una vez que salimos de este bucle aquí, y básicamente este método llega a su fin, entonces el trabajador ya no está funcionando. En ese punto, el trabajador ya no está vivo. Y así básicamente queremos estar buscando los puntos cuando, por ejemplo, este trabajador se rompe de su bucle de ejecución o termina aquí su método de ejecución. En ese punto ya no está vivo. En ese punto lo sabemos, de acuerdo, este trabajador ha terminado. Por lo que podemos empezar a enviar y hacer a los consumidores downstream. Por supuesto, si tenemos más instancias de las que necesitamos asegurarnos de que no sea sólo una instancia la que terminó, sino que es cada instancia la que terminó. Entonces lo que vamos a hacer es que vamos a decir por trabajador, nombre de trabajador en, y ahora sólo queremos tomar a nuestros trabajadores. Entonces dando vueltas sobre nuestros trabajadores. Y aquí vamos a hacer un seguimiento de la vida total de hilos de los trabajadores. Entonces debido a que cada uno de nuestros trabajadores puede tener múltiples hilos, solo queremos hacer un seguimiento del número total de hilos que actualmente se están ejecutando. Entonces vamos a estar dando vueltas por cada lado. Vamos a decir para hilo de trabajo, igual que aquí, haciendo un bucle sobre cada hilo que hacemos un seguimiento aquí. Entonces, ¿cómo podemos comprobar si es lifo? En realidad es relativamente fácil. Todo lo que tenemos que hacer es que tenemos que tomar nuestro hilo y solo podemos usar este método está vivo. Y esto nos dirá si el trabajador sigue vivo o no. Entonces podemos decir si un trabajador está vivo. Entonces sólo queremos incrementar esto en uno. Entonces básicamente por cada trabajador que tenemos que está vivo, entonces vamos a incrementarlo por uno. Y así en la anterior, si no tenemos a ninguno de estos trabajadores con vida, así que si todos los hilos han terminado, ahora podemos empezar a tomar las señales aguas abajo desde aquí, y podemos empezar a mandar hecho a ello. Entonces podemos decir, todo lo que necesitamos para conseguir las indicaciones aguas abajo. Y cuatro aquí, tenemos que revisar primero, si no ninguno, porque no podemos tener casos. Por ejemplo, nuestro trabajador de Postgres no tiene colas de salida. Entonces queremos asegurarnos de que las señales aguas abajo que tenemos, que éstas existen. Entonces si la reducción indica o no ninguna, entonces queremos, para Q aguas abajo en las señales aguas abajo que tenemos para cada trabajador. Entonces lo que estamos haciendo es que estamos dando vueltas, Aquí hay un archivo YAML. Estamos dando un bucle sobre cada uno de estos QS de salida aquí. Ya que esa voluntad, de lo que estamos haciendo un seguimiento en esta variable cuz downstream es que estamos haciendo un seguimiento de todas las colas de salida. Entonces podemos llamar a esto para aguas abajo Q. Podemos llamar a esta salida Q para especie de ser más en realidad consistente con una sintaxis que tenemos aquí. Por lo que podemos usar esto para enrutar para cada salida Q y aquí. Entonces queremos tener número de consumidores. Entonces ahora queremos saber para cada salida Q, cuántos hilos están leyendo realmente desde aquí. Bueno, rastreamos eso aquí mismo. Por lo que sabemos para cada q cuántos hilos o leer de ella. Entonces el número de consumidores aquí. Simplemente podemos leer de este diccionario que hemos configurado antes aquí. Y entonces podemos decir por mí en rango número de consumidores. Y ahora para cada uno de estos, podemos enviar hecho a esta salida Q. Así que en realidad tenemos que conseguir este FAQ. Entonces y lo haré, voy a recapitular en un segundo. Pero primero, vamos a escribir esto para que tengamos, ya sabes, lo completo aquí. Entonces vamos a estar tomando nuestra salida Q. Y al igual que tenemos aquí, vamos a estar poniendo hecho. ¿Está bien? ¿ De acuerdo? Y luego lo último que tal vez podamos hacer, si no tenemos más de estas amenazas con vida, entonces realmente podemos quitar, podemos quitar a ese tipo de trabajador de nuestro rastreo para que ya no necesitemos un rastrearlo. Y ahora, de acuerdo, entonces ¿cómo vamos a salir de este bucle infinito mientras queremos también hacer un seguimiento del total de trabajadores vivos. Y básicamente, probablemente podamos hacer esto aquí arriba porque queremos hacer un seguimiento de esto en cada iteración. Entonces cada vez que estamos pasando y para cada uno de los trabajadores, queremos saber, ya sabes, cuántos trabajadores y total vivos. Vamos a estar repasando a todos los trabajadores. Y entonces aquí en realidad podemos decir, bueno, o bien podemos hacer mientras es cierto, y entonces se puede decir aquí, si el total de trabajadores viven es igual a 0, entonces podemos salir de ella. O podemos decir, mientras que total bookers vivos porque no igual a 0. Pero entonces por supuesto tenemos que definirlo aquí arriba y gritar. Entonces en este caso, cualquiera de estas opciones está algo bien. Y realmente depende de lo que quieras ir con, supongo aquí. Bueno, ya que tenemos esto ahora y sólo vamos a ir con esto. Es un poco incómodo tener como esta duplicación aquí. En este caso, también podría ponerlo hacia atrás para que básicamente contemos, reiniciemos el contador al final. Pero realmente no va bien. En realidad no queremos restablecer el contador al final porque entonces estaríamos saliendo de este bucle. Entonces sí, sí queremos tenerlo en la parte superior aquí. De acuerdo, así que vamos a repasar lo que tenemos. Y en realidad lo primero también que voy a hacer es que sólo voy a comentar todo esto porque ya no queremos que nuestros hilos, por supuesto, estén enviando estas señales hechas. Pero en cambio queremos que nuestro principal ducto sea un poco responsable de esto. Entonces, ¿qué acabamos de hacer? Bueno, en primer lugar, sacamos a los trabajadores de unión de nuestro paso de proceso de tubería. Porque si hacemos eso, entonces básicamente este paso aquí va a estar bloqueando y no queremos eso. Por lo que hemos sacado eso de este paso aquí. Y en nuestros trabajadores inicializados, hemos agregado dos atributos adicionales que estamos rastreando. Cada uno de ellos tiene un diccionario. Por lo que para cada trabajador, por rastrear lo Q, envían dos. Entonces estamos rastreando su salida Q. Y para cada q, también estamos, somos para cada trabajador, también estamos rastreando como de qué q están leyendo y cuántas instancias están leyendo desde la cola. Nuevamente, haciendo la suposición de que cada taco es específico de un trabajador. Por lo que no podemos reutilizar el símbolo Q, por ejemplo. Aquí, así no funciona porque entonces van a estar difundiendo los datos que vienen de aquí. Y esto va a ser leyendo algo de ello, y esto va a ser leyendo algo de ello. Pero ninguno va a conseguir el conjunto de datos completo y completo. Entonces no podemos hacer eso. Entonces con esta suposición, básicamente estamos diciendo, Vale, cada tipo de trabajador y podemos escalar el número de instancias aquí Aún no hay problema. Pero cada tipo de trabajador que tenemos aquí tiene asociada una cola específica para que sepamos ahora, bien, por cada q, sabemos que esto es cuántas instancias están consumiendo de ella, que podemos ver aquí. De acuerdo, Así que ahora solo estamos haciendo un seguimiento de esta estadística Q. De modo que más adelante cuando llamemos a este método de ejecución o, y luego los siguientes pasos de este método de ejecución y traerte están usando la ejecución porque hemos convertido esto en una clase de subprocesos. Ahora estamos iniciando un bucle que básicamente va a hacer un seguimiento de como monitorización para nosotros en una mano. De hecho llegaremos a implementar el monitoreo en un segundo. Pero también se va a estar cuidando de enviar hecho a las colas de salida. Lo cual de nuevo es importante porque si lo hacemos aquí, que una amenaza podría terminar, podría empezar a enviar hecho, y otro hilo podría estar ejecutándose, y en realidad estará agregando valores después de que el hecho aquí tiene sido enviado. Pero, ya sabes, con eso, estamos enviando como 20 mensajes hechos. Entonces los consumidores downstream en realidad todos van a estar parando porque van a estar recibiendo el valor w1. Y luego van a ser algunos mensajes en la cola que se van a dejar sin leer. Por lo que queremos evitar eso y solo queremos enviar hecho una vez que cada trabajador haya terminado. Entonces la forma en que estamos haciendo eso es que estamos dando un bucle sobre cada trabajador que tenemos. Y por cada trabajador estamos repasando cada hilo y solo estamos comprobando si ese hilo está vivo o no. Y ahora lo que esto significa es que un hilo ya no está vivo si termina aquí su método de ejecución. Entonces, básicamente si se rompe de este bucle de ejecución, ese punto de hilo ya no está vivo. Y esto no se activaría. Pero si aún está vivo, eso significa que todavía está en este bucle de carrera aquí. Y así solo estamos haciendo un seguimiento del número total de hilos de trabajadores que están vivos. Y si ninguno de los hilos está vivo, eso significa que cada trabajador ha terminado. Se estalla si es loop. Entonces ya sabemos, vale, Ahora queremos mandar hecho a todas las señales a las que escribe. Por lo que necesitamos recorrer cada salida única Q, m por cada salida única Q, necesitamos enviar hecho un número de veces basado en el trabajador que lee desde esta cola, que es ésta. ¿ Cuántas instancias ese bar? Entonces por ejemplo, en este caso, tenemos seis instancias leyendo desde Postgres subiendo. Y así queremos asegurarnos de que enviemos hecho al menos seis veces para que cada instancia aquí lea el mensaje hecho. Y esa es la lógica que aquí hemos implementado. Y luego al final, solo estamos sacando a este trabajador del rastreo para que, sabes, una vez que se haga como que ya no necesitamos hacer lo mismo. Sabemos, como una vez que enviamos todo esto hecho aquí, entonces, ya sabes de ese trabajador ha terminado totalmente. Ya no necesitamos rastrearlo. Entonces hay una cosa más que yo sólo quiero añadir aquí, que va a ser estadísticas de los trabajadores. Y lo que quiero hacer aquí es sólo agregar en el nombre del trabajador, así como cuántos trabajadores están vivos. Y luego al final aquí, quería imprimir pasos de autotrabajador. Ahora esto es sólo una especie de monitoreo para nosotros para que realmente podamos ver lo que está pasando. Y aquí en nuestro hilo principal, he reemplazado este proceso de canalización fue solo el paso de inicio para que realmente iniciemos este método de ejecución aquí. De acuerdo, así que no solo activas mi entorno virtual. Y luego sigamos adelante y corremos y realmente necesitamos encender Postgres a. Porque en este momento mi instancia de Postgres o servidor de Postgres no se está ejecutando localmente, así que solo hay que asegurarse de que se inicie. Entonces vamos a ver, Ahí vamos. Está bien, así que sigamos adelante y ejecutemos esto. De acuerdo, tenemos un error aquí. No se llama al método de inicialización. Entonces queremos inicializar la amenaza por supuesto también. Está bien, así que intentemos eso una vez más. De acuerdo, Así que está funcionando de nuevo. Entonces para esto actualmente, bueno, en primer lugar, tenemos de nuevo este tiempo de extracción, que es sólo porque no los estamos llamando métodos de unión. Entonces esto es como lo mismo que teníamos antes de que llueva porque no estamos llamando a unirse aquí. Básicamente salta para escuchar tipo de casi de inmediato. Pero la otra cosa es que parece que no estamos imprimiendo todavía las estadísticas aquí. Entonces lo haré, claro. Eso es una especie de error aquí. Si ponemos esto a 0 aquí arriba, entonces por supuesto que ni siquiera vamos a estar entrando en este bucle. Entonces déjame arreglar eso. Y justo aquí arriba, di que ese era un poco mi botón. Si establecemos que esto sea 0, si aquí, y luego si decimos, bien esto no es 0, bueno, esto ya es 0, así que ni siquiera vamos a entrar a este bucle. Entonces saca esto. Pero en realidad hay una cosa más que yo quería hacer, que es tener una lista de trabajadores que deberíamos eliminar. Y en lugar de eliminarlo inmediatamente aquí, en realidad quiero anexar ese nombre de trabajador y luego eliminarlo más tarde. Por lo que quiero poder escuchar tal vez para trabajador y para eliminar aquí, quería liderarlo. El motivo es que si borramos aquí arriba, seguimos iterando, como si todavía estuviéramos dando un bucle sobre esto. Y así por borrar mientras estamos en bucle, entonces Python se va a molestar con nosotros. Entonces no queremos hacer eso. Sólo queremos quitar una vez que hayamos terminado el bucle, razón por la cual lo estoy manteniendo así. Entonces intentemos eso una vez más. De acuerdo, ahí vamos. Por lo que ahora estamos viendo nuestras estadísticas reales de los trabajadores. Para que podamos ver a nuestro trabajador wiki aquí terminado. Y también notamos una especie de subir aquí. En realidad estamos viendo aquí a nueve trabajadores, lo cual por supuesto no es cierto. Esto no se equivoca nuestro monitoreo, porque aquí queremos mostrar vivos los hilos de los trabajadores totales, no el número total de réplicas vivas, que es una especie de agregarlo. Ahora algo que debería estar pasando pero en realidad no está sucediendo. Y yo sólo voy a bajar este tiempo de sueño aquí sólo para asegurarme de que esto no sea un problema. Pero podemos ver al pasar por nuestros registros que en realidad nuestros trabajadores están llegando a tiempos de espera y que no están siendo detenidos por nuestras señales de stop. Entonces por supuesto que no queremos eso. Queremos asegurarnos de que sus tiempos de espera se estén alcanzando átomos. Entonces no queremos eso. Queremos asegurarnos de que, ya sabes, nuestros trabajadores en realidad están parando con el método que estamos haciendo que tenemos aquí. Entonces echar un vistazo de nuevo a nuestro bucle, bueno, esto debería ser no es ninguno. Porque queremos ir si realmente tenemos trabajadores aguas abajo. Entonces sigamos adelante y probemos eso una vez más. Y ahí vamos. Entonces ahora arreglamos el problema que teníamos antes, que era que no estábamos enviando hecho desde aquí, sino que llegamos a tiempos de espera. Y por supuesto, podemos ver que fue genial tener estos tiempos de espera porque tipo de ayuda a combatir parte del error real que teníamos aquí. No estábamos un poco atrapados en un bucle infinito. Pero sí, así que hemos terminado un poco esta parte, que en realidad es extremadamente agradable porque ahora ya no estamos enviando hecho desde aquí. Entonces sigamos adelante y quitemos esto también. Y de esa manera cuando tenemos múltiples instancias, entonces no es si la primera termina y manda hecho, entonces, ya sabes, todo lo demás aguas abajo se va a parar. Y aunque solo enviemos hecho una vez, entonces ahí entramos en problemas como lo que pasa si mientras el número de trabajadores aguas abajo no es igual al número de trabajadores que tenemos actualmente. Si tenemos más trabajadores downstream y no van a terminar y van a llegar a tiempos de espera. Y aunque lo hagan, entonces estarán parando antes de que todos los trabajadores se pare F-, lo que significa que nuestro desempeño va a bajar. Entonces tenerlo de esta manera, Es mucho más bonito porque ahora estamos enviando hecho. Una vez que conocemos todos estos, todos estos trabajadores realmente han terminado. Ahora hay una cosa más corta que quería mostrarte y sé que estamos haciendo un poco largo aquí, pero en realidad no podemos ejecutar esto porque desafortunadamente no funciona en Mac, pero esto sí funciona en Linux. Por lo que estamos haciendo un seguimiento de las estadísticas de nuestros trabajadores aquí. Y probablemente no nos gustaría hacer algo similar para q dice que es correcto, solo entiende cuánto datos hay en realidad en nuestras señales. Ahora, hay este método si miramos la cola. Entonces otra vez, no va a ser como escribir la cosa completa porque no va a correr de todos modos. Pero podemos decir como para Q en, en nuestro QRS y luego solo tener esta cola. Y entonces aquí podemos ver el tamaño de la cola. Entonces esto es de nuevo, algo que no está todo disponible, desafortunadamente en Mac, pero en Linux, esto es algo que realmente puedes hacer es que puedes obtener los tamaños de cola. Ahora, um, y esto es realmente bonito porque como básicamente, sabes, eres capaz de monitorear cuánto hay en cada cola. Y con esto, entonces eres capaz de decir, Oh, vale, ya sabes tantos trabajadores o tienen, pero en realidad puedo ver como, oh, esta Q súper llena. Entonces en realidad voy a agregar más instancias allí y tal vez saqué a algunos trabajadores a otro lugar donde el tamaño de cola siempre es 0. Por lo que tener esta herramienta de monitoreo Q también es realmente agradable. Y por supuesto podemos ponerlo en como también como oh, Q empieza así. Y entonces aquí podemos, ya sabes, igual que hacíamos antes, en lugar de simplemente imprimir esto. Se puede agregar esto aquí y luego aquí podemos imprimir como puntos acusados. Ahora desafortunadamente, y ya verás si ejecuto esto, esto va a causar un error porque básicamente esto no se implementa en Mac con suavidad. Por lo que esto se ejecutaría en un sistema Linux, pero desafortunadamente no se ejecuta en Mac. Entonces sí, no podemos usarlo aquí. Pero la mayoría de las veces si realmente eres como usar cosas en producción y probablemente se esté ejecutando en un sistema Linux porque se implementará como una imagen de Docker o algo así. Entonces en esos casos, en realidad eres capaz de dejar esta pieza de código en. Y también podrás monitorizar las estadísticas de colas. Y con eso, entonces podrás obtener más información revisando los registros. Amplía el número de instancias postgres. Reduzco el número de instancias tal vez porque siempre es 0. Y así no tiene sentido tener esas muchas instancias si nuestra q siempre es 0. Y así sí, sin ojalá puedas tomar esta información que estás obteniendo y tomar decisiones más inteligentes sobre cómo estás, cuántas instancias realmente estás atribuyendo a cada uno de los diferentes trabajadores que tienes aquí. Pero sí, ese tipo de me gusta nos lleva al final de esta optimización aquí. Y en realidad nos estamos poniendo muy, muy cerca de terminar esto. Entonces lo único que queda, que es lo que cubriremos en el siguiente video, es básicamente que queremos tomar algunas de las definiciones que tenemos, específicamente como la ubicación del ducto o algo así. Y queremos hacerlo, o quiero ponerlo en como una variable de entorno. Pero de nuevo, hablaremos de eso en la siguiente lección. 14. Limpieza de el programa final: Muy bien, entonces en esta lección sólo vamos a estar haciendo un poco de limpieza rápida, básicamente yendo y simplemente moviendo esto a una variable de entorno, pero luego también teniendo como una variable de entorno local que podemos usar para pruebas reales y cosas así así. Entonces sólo que todo esto se vuelve un poco más libre basado en cada vez que queramos iniciar el programa, podemos como definirlo en ese sentido. Entonces tú eres, por supuesto, lo primero que vamos a hacer es que vamos a decir que este ambiente se ponga, sólo voy a llamar a esto nuestra ubicación del ducto. Y aquí también necesitamos importar OS. Ahora lo que voy a hacer es crear un archivo ENV punto, que va a ser nuestras variables de entorno. Y en realidad estoy, déjame renombrar esto porque voy a llamar a este pensamiento y local. Entonces esto va a ser como nuestras variables de entorno local. Eso significa que si queremos tener más adelante como variables de entorno de puesta en escena y producción, entonces podemos cambiar cada una de estas n dependiendo de lo que queramos probar. Podemos usar cosas diferentes. Yo soy principalmente tú quieres estar probando probablemente en local y puesta en escena. Por lo que aquí vamos a definir nuestras variables de entorno. Y sólo vamos a, sólo vamos a tomar esto por aquí. Entonces lo que este experto nos permite hacer en un segundo cuando usamos este comando fuente, es que somos capaces de hacerlo, mientras somos capaces de fuente del archivo de entorno. Y entonces lo que significa es que esta exportación solo tendrá como set estas variables de entorno en nuestra terminal aquí. Entonces de esa manera sólo podemos, ya sabes, tenerlos definidos en nuestra terminal, en nuestra instancia terminal en ejecución. Y luego cuando lo ejecutemos, entonces vamos a estar usando esas variables de entorno. Entonces agregamos la ubicación de la tubería, pero en realidad, pasemos por unos trabajadores diferentes porque en nuestro trabajador de Postgres también estamos usando variables de entorno. Entonces tenemos usuario de Postgres, que sólo va a ser una cadena vacía. Tenemos la contraseña de Postgres, que también va a ser una cadena vacía, y el caso de Mac en el caso de windows aquí vas a tener valores establecidos aquí. El anfitrión de Postgres va a ser nuestro anfitrión local. Y la base de datos Postgres va a ser lo que tenemos aquí. Ahora en este caso, realidad voy a estar quitando esto de aquí. Entonces de esa manera sólo lo tenemos definido aquí. Por lo que sé, este abastecimiento de entorno y esta sintaxis es específico para como sistemas Linux y Mac. Pero ya sabes, si estás en un Windows, aún puedes volver a tener la sintaxis similar, como hablamos de la última lección. En realidad vas a ser, ya sabes, si lo estás haciendo o alguien más te está ayudando a hacer en desplegarlo en algún lugar, que esto en su mayoría siempre se va a ejecutar a diferencia de un sistema basado en Linux. Entonces, ya sabes, podrás usar este entorno. Y la sintaxis del entorno funcionaría también en un Windows. Pero específicamente como esta sintaxis explotando de esta manera, estoy bastante seguro de que es igual que Linux y Mac específico. Pero no te preocupes porque esto es como las etapas finales de limpieza. Y de nuevo, si lo estás ejecutando en otro lugar, realidad puedes pasar esas variables de entorno. Y así tenemos nuestras variables de entorno aquí. Y tenemos aquí. Aquí tenemos que decir, si no tenemos una ubicación de tubería, entonces básicamente vamos a salir con un código de salida. Sets fallaron y vamos a decir, soy ubicación de tubería no definida. Y entonces si sí queremos tener el tiempo de extracción tu tubo, porque nuestro ejecutor principal, nuestros ejecutores YAML I en realidad también una amenaza ahora, bueno podríamos hacer está bien, podríamos llamar a esto como mostrar trabajadores. Pero realmente sabemos mirando esto, nuestro hilo principal aquí, o nuestro hilo obrero amarillo, sólo va a estar saliendo ánodo una vez que todos los trabajadores y Saturno lo hayan hecho. Entonces sólo una vez que todos los trabajadores dentro estén hechos ¿ realmente nos va a gustar escaparnos de aquí de todos modos? Entonces realmente también podemos simplemente llamarlo, llamar al join on aquí si queremos conseguir este tiempo de extracción. Entonces Sigamos adelante y solo probemos cómo funciona esto. Vamos a activar nuestras variables de entorno local para que veamos si quiero imprimir esta variable. De acuerdo, entonces ahora está definido. Y este eco es sólo un comando terminal que podemos usar. Y este símbolo de dólar aquí básicamente significa que queremos imprimir el acceso al valor de una variable, que hemos definido aquí. Entonces esto es muy similar, al igual que definir variables en Python es justo, la sintaxis es un poco diferente para como el terminal, pero básicamente está imprimiendo el valor de la ubicación de la tubería. Y aquí estamos definiendo la variable de ubicación de la tubería para que sea de este valor. Muy bien, así que intentemos volver a ejecutar nuestra función principal y solo asegurarnos de que todo funcione correctamente. Y después de que hayamos hecho estos cambios, que parece que lo es. De acuerdo, y así también tenemos tiempo de extracción adecuado. Y entonces una cosa más que quiero hacer es, quiero decir, probablemente no queremos estar imprimiendo todo esto todo el tiempo. Ya sabes, esto es más para fines de prueba mientras lo estábamos teniendo. Entonces solo podemos quitar esa impresión y la ejecuto una vez más solo para asegurarnos de que la salida también esté limpia. Entonces todo se ve realmente limpio. Y sí, ahí vamos. Este tipo de like nos trae también podría eliminar esto básicamente cualquier cosa innecesaria comentada. Y sí, este tipo de nos lleva al final de todo este tutorial de subproceso donde hemos construido y ya sabes, todo este programa de subproceso para hacer como desguace y carga de bases de datos y todas esas cosas solo para moverse. Los temas son como los tiempos de espera que experimentamos en ese momento fueron los periodos de espera que se asocian a la comunicación de red. Entonces espero que hayas disfrutado de esto, hayas aprendido mucho y puedas transferir algo de esto ya sea a tus propios proyectos o a tu propio trabajo. Y nuevamente, hacer uso de esto específicamente en los casos en que los factores limitantes son los tiempos de comunicación de la red. Nuevamente, el subproceso no es óptimo para optimizar la computación cargas de trabajo pesadas porque no estamos haciendo uso de como más CPU. Es justo cuando estamos esperando a que las redes respondan. Tenemos comunicación de red que otros hilos pueden seguir ejecutándose mientras los otros hilos solo están esperando alguna respuesta de algún otro lugar a través de la red. Entonces de nuevo, ya sabes, gran trabajo al completar esta sección del curso. Espero que lo hayan disfrutado. Espero que hayas aprendido mucho. 15. Bloqueado: De acuerdo, así que ahora que hemos construido esas aplicaciones de subproceso bastante cool y algo que hemos usado mucho dentro en realidad fueron todas estas indicaciones, que si recuerdas al principio cuando estábamos hablando del QRS. Veamos dónde los inicializamos por aquí. Por lo que hablamos de que estos sean seguros para subprocesos. Entonces, ¿qué significa eso exactamente? Y esta lección, rápidamente quise pasar por encima del bloqueo y algo conocido como condiciones de carrera para que puedas entender algunas cosas de las que tal vez tengas que estar cauteloso al hacer el subproceso. Entonces voy a crear un nuevo archivo aquí. Voy a llamar a no cerrar. Y lo que vamos a hacer aquí es que sólo vamos a importar threading. Y vamos a tener una pequeña función. Vamos a tener un contador global que se fijará en 0. Y vamos a tener una pequeña función llamada incremento. Y esto nos va a llevar nuestro mostrador y sólo vamos a tener un bucle aquí. Diremos para mí en rango, y luego empezaremos con 10. Yo estoy usando poderes de 10 aquí, que on-off para escribir diez y luego un 100 y 1000. Entonces voy a usar poderes de 10 solo para hacer esto un poco más fácil y ya verás por qué en un segundo. Entonces vamos a tener un bucle aquí que actualmente sólo hace diez iteraciones. Y durante cada iteración se va a implementar un contador por uno. Ahora, aquí solo estoy llamando a la variable global en caso de que no hayas visto esto antes es ya que estamos modificando este valor, en realidad necesitamos asegurarnos de que llamamos a la variable global en la parte superior aquí, ya que no solo estamos accediendo a ella, pero en realidad lo estamos modificando. Entonces ahora lo que voy a hacer es crear cuatro hilos. Voy a decir para mí en el rango cuatro, vamos a crear un hilo. Y nuestro objetivo va a ser esta función de incremento. Y luego sólo vamos a anexar estos y luego vamos a empezar todos ellos. Entonces vamos a decir t dot start. Y luego también vamos a llamar al método join para asegurarnos de que esperemos hasta que estén todos terminados. Y luego al final, vamos a imprimir nuestro valor de contador. Programa tan sencillo. Realmente lo que estamos haciendo es que aquí tenemos una variable global, contador inicializado a sigma. Y entonces sólo tenemos una función que va a tomar esa variable global que va a incrementarse diez veces. Y vamos a correr esto a lo largo de cuatro hilos. Por lo que cada hilo va a llamar a esta función. Entonces, en total, deberíamos tener un valor aquí de 40. Ya que tenemos cuatro hilos, cada hilo llama a la función. Cada llamada de función incrementará este valor en 10, así que 4 veces 10, eso va a ser 40. Entonces sigamos adelante y ejecutemos esto. Está bien, Porque se ve bastante bien. Entonces tratemos de incrementar este número aquí. En lugar de hacer diez, Hagámoslo 1000. Por lo que va a ser 10 a la 3. ¿ Todo bien? Y sigamos adelante y ejecutemos esto. De acuerdo, Cuatro mil, Eso es exactamente lo que esperamos. Intenta incrementarlo una vez más. En lugar de hacer 1000 operaciones, ahora vamos a hacer un millón. Entonces lo que esperamos ver aquí van a ser de 4 millones. Desde cada valor sólo vamos a estar incrementando un millón de veces y vamos a hacer eso en cuatro hilos. Entonces sigamos adelante y ejecutemos esto. Oh, bueno eso es raro. ¿ Por qué estamos consiguiendo esto y no 4 millones? Entonces lo que hemos encontrado aquí es algo llamado condición de carrera, donde básicamente tenemos una variable compartida, que es lo que tenemos aquí. Y varias entidades diferentes están tratando de acceder a ella al mismo tiempo. Entonces lo que está pasando en algún momento es que tenemos nuestro contador, que es igual a cualquier valor x. Y entonces tenemos un hilo. Un hilo lo lee y ve oh, contadores x. Y luego va a intentar incrementarlo después. Pero al mismo tiempo, tenemos otro hilo, digamos hilo T2, que también ve contador es igual a x Entonces lo que sucede es cuando tenemos hilo uno está diciendo contador es igual a contador más uno. Entonces eso significa un contador de esencia igual a x más 1. Y entonces también tenemos hilo para hacer lo mismo. Entonces tenemos en este caso es el resultado que obtenemos es en realidad contador es igual a x más 1, pesar de que hemos tenido dos hilos acceden a ella. Y la razón por la que esto sucede es porque a veces estos valores básicamente ven lo mismo y luego llaman a sus operaciones, pero no lo leyeron secuencialmente. Por lo que no leían uno tras otro. No se ejecutó así. En cuyo caso habríamos tenido aquí el valor adecuado de esto, pero lo leen al mismo tiempo o lo suficientemente cerca antes de que pueda suceder esta operación de incremento. Eso Después de esta operación de incremento ocurre a través de los dos hilos. Y en este ejemplo, todavía sólo nos queda con x más 1 porque vieron el mismo valor inicialmente. Y entonces este es el tipo de problema que estamos viendo aquí. Obviamente estamos viendo que sucede mucho más de una vez. Pero podemos ver eso a medida que aumentan estas operaciones en estos hilos. Y en este caso sólo tenemos que subir este número para asegurarnos de que aumentemos nuestras posibilidades de que algo así suceda. Estamos entrando en esta condición de carrera donde el valor está siendo accedido por múltiples objetos al mismo tiempo, cada uno está realizando la operación y luego su anulando el valor. Pero a veces los cambios que estamos recibiendo no son los que esperamos. Dado que dos hilos ambos incrementan x por uno. Y así no estamos consiguiendo un más dos aquí, estamos consiguiendo un más uno. Ahora obviamente este no siempre es el caso porque sí tenemos, ya sabes, estamos, estamos casi a mitad de camino ahí. Si miro estos números, grite, así que estamos a mitad de camino ahí. Pero obviamente esto está pasando bastante. Entonces, ¿qué podemos hacer al respecto? Bueno, está esta cosa genial llamada candado, que también es por eso que hemos llamado a nuestro archivo aquí bloqueando. Entonces vamos a entrar en la clase de subprocesos y vamos a inicializar un candado. Ahora, los dos métodos que están disponibles en esta clase de ley que realmente nos interesan van a ser bloqueados dot adquieren y Locke, Locke dot release, comentan esos fuera. Entonces estos son los que van a ser pruebas interesantes. Y lo que hacen estos es poner un, básicamente iniciar un candado. Entonces en este punto se trata de una operación de bloqueo y no puede pasar nada más mientras se adquiere este candado. Por lo que este hilo básicamente ha reclamado el candado. Y está diciendo que estoy corriendo ahora mismo hasta que lo suelte o en realidad hasta que cualquier otro hilo suelte que bloquee, entonces nada que ya no podamos encontrar estas, estas condiciones de carrera. Entonces lo que sucede en este caso es amenaza. Se va a iniciar la amenaza y se va a leer la contra-variable. Pero primero hilo va a empezar y va a decir, Oh, yo soy garganta es, hilo está bloqueando. Y luego Se va a leer la variable contador. Se va a incrementarlo en uno. Y luego es un poco decir liberando cerradura. Y luego vamos a tener un hilo diferente, que también se va a bloquear. Y luego te va a ver el resultado aquí arriba, que es x más 1. Y luego vamos a tener x más 1 más 1, que va a ser x más 2. Y entonces estamos nuevamente liberando la cerradura. Ahora obviamente en este caso, estamos rompiendo algo del paralelismo que estaba disponible para nosotros y tipo de forzar operaciones secuenciales. Ahora obviamente, no queremos encerrarlo todo todo todo el tiempo porque de lo contrario no vamos a estar ganando mucho beneficio. Pero realmente otra vez, si lo piensas hasta el muy, muy principio, estamos usando el subproceso, principalmente cuando tenemos bloqueando operaciones IO de red. Entonces cuando pasa mucho tiempo entre los viajes de ida y vuelta de la red, y no queremos simplemente estar sentados inactivos esperando una respuesta. Ahí es cuando el enhebrado realmente va a prosperar para nosotros. Entonces en este caso, cuando estamos haciendo operaciones localmente, podemos usar el bloqueo para asegurarnos de que nuestras operaciones van a ser consistentes y que ahí que no nos encontramos con ninguna condición de carrera. Y entonces realmente otra vez, el punto de la estrangulación va a ser más hacia IO de la red. Por lo que obviamente solo ten en cuenta los efectos de eso que tendrás cuando utilices el bloqueo. Pero sigamos adelante y veamos esto en acción. Entonces lo que vamos a hacer cada vez antes de incrementar el valor, porque vamos a decir bloqueo adquirir. Y después vamos a soltar este candado. Entonces sigamos adelante y corramos esto una vez más. Y ahí vamos, obtenemos el resultado esperado. Ahora. Entonces hay un método que yo, que recomendaría usar aquí aunque que creo que es un poco más limpio luego bloquear que adquirir, bloquear y soltar. Porque cuando llamas a adquirir, solo tienes que recordar llamar también a liberación. De lo contrario vas a empezar a tropezar con problemas. Entonces veamos esto a pequeña escala. Y vamos a ejecutar esto. Está bien. Entonces estoy terminando una vez porque no estamos liberando la cerradura. Entonces básicamente adquirimos un candado y en nada más puede correr hasta que este candado sea liberado por algo. Entonces voy a interrumpir esto. Entonces, obviamente, no queremos olvidar esto. Entonces la forma más fácil con la que podemos hacer esto dentro de Python es usar el Gestor de Contexto. Entonces lo que podemos decir es en cambio, con Locke, vamos a incrementar el contador en uno. Entonces lo que esto hace es todo dentro de este guión aquí. Entonces tocando. Y tú estás cerrando. Todo dentro de este sangría aquí va a estar dentro del bloque dot adquirir y luego bloqueado liberación. Tan pronto como salgamos de este sangría, donde esencialmente llamando aquí loc dot release. Y en el inicio mismo de esta nnd, vamos a llamar a laptop acquire. Pero de esta manera es obviamente un poco más limpia porque no tenemos que llamar al lanzamiento real. No tenemos que asegurarnos de que no los olvidemos porque eso puede ser problemático, sobre todo si tienes programas que van a correr por un tiempo de todos modos. Y te lleva bastante tiempo descubrir que en realidad te olvidaste de soltar la cerradura. Entonces, en cambio, podemos simplemente usar el gestor de contexto y decir con bloqueo. Y entonces todo aquí dentro va a ser entre esta cerradura que adquirió al principio y encerrada o al menos al final. Y no tenemos que preocuparnos por olvidar potencialmente que nos olvidamos de soltar la cerradura. Y así podemos ver también volvemos al diez al seis que estábamos a las cuatro. Aquí, también deberíamos conseguir la fórmula que esperábamos. Entonces esto es solo una cosa importante a tener en cuenta porque anteriormente estábamos usando colas para todo lo que son seguros para subprocesos. Pero a veces si haces otras cosas, sobre todo si estás accediendo a variables compartidas, entonces puede haber problemas ahí. Entonces solo piensa en cómo está interactuando tu programa. Y si necesitas usar cerraduras y si sabes que estás en ellas. Si has escrito un programa donde potencialmente puedas realmente encontrar una condición de carrera, solo ten en cuenta que el bloqueo va a ser una herramienta importante para usar ahí para asegurarte de que realmente obtienes los resultados correctos que tú están esperando. 16. Introducción a multiprocesado: De acuerdo, así que ahora que hemos visto una buena cantidad de cosas sobre el enhebrado, sigamos adelante y echemos un vistazo al multiprocesamiento. Ahora, primero solo quiero volver a escribir un sencillo script de subprocesos. Y entonces en realidad ya tengo mi monitor de actividad abierto para que podamos monitorizar o el uso de CPU un poco. Y luego vamos a ver cómo cambia eso cuando vamos al multiprocesamiento. Entonces voy a decir desde un threading, voy a importar hilo. Vamos a tener una función aquí que sólo va a decir valores de chequeo en lista. Y va a tomar en algunas listas, sólo llamaremos a eso x. Y lo que va a hacer aquí es que va a tener un bucle. Diremos para mí en rango. Y hagamos diez al poder de ocho, así que 100 millones. Y todo lo que vamos a hacer es que sólo vamos a comprobar si soy una x. Y luego vamos a crear algunos hilos. Entonces vamos a decir número de hilos va a ser cuatro. Y tendremos nuestra lista de hilos aquí. Haremos un seguimiento de ello. Y voy a decir para yo en rango número de hilos, vamos a crear el hilo. Lo vamos a tener. El objetivo de la función sea este valor de comprobación en la lista. Y los argumentos que le vamos a proporcionar va a ser la lista que queremos usar. Entonces diremos lista de comparación. Va a ser igual a 1, 2, 3. Proporcionar eso como insumo. Entonces lo que vamos a hacer es que sólo vamos a revisar más de cuatro hilos diferentes buceando sobre un 100 millones de valores para ver si alguno de estos valores está dentro de este hilo. Entonces básicamente solo haciendo algunas operaciones de CPU sin ningún componente de red. Y por supuesto queremos anexar esos hilos a nuestra lista donde los hacemos un seguimiento. Y diré para hilos tn, vamos a iniciar nuestros hilos y diremos para 10 hilos, entonces también vamos a unirnos o amenazas. Y también solo importemos tiempo aquí. Y justo antes de que empecemos, diremos que la hora de inicio es tiempo de espera. Y entonces diremos que todo tomó. Haremos tiempo.Deltatime menos tiempo de inicio, segundos. De acuerdo, entonces lo que hemos hecho aquí es sólo todo programa básico de subprocesos. Empezamos y nos unimos a nuestros hilos, por supuesto, como si hubiéramos cubierto mucho recientemente. Y sólo tenemos la lista simple que contiene tres valores y para cuatro hilos diferentes, sólo vamos a en cada bucle de hilo. Entonces vamos a estar haciendo muchas operaciones repetidas, repetidas en realidad, para cada una de estas, sólo vamos a comprobar si el valor está dentro de ahí. Y entonces sólo vamos a cronometrar toda esta operación para ver cuánto tiempo lleva todo esto. Por lo que voy a empezar aquí nuestra función principal. Y si vamos a nuestro monitor de actividades, entonces podemos ver que va a haber, por supuesto, un pequeño pico, que es lo que esperaríamos. Porque obviamente algo va a estar funcionando. En realidad podemos ver nuestro proceso de Python aquí están ahora solo haciendo trabajo. Y va a estar tomando un poco de tiempo sólo, ya sabes, terminar todo esto. Pero ojalá debiera terminar pronto. Muy bien, Así que tomó unos 33 segundos y podemos ver que nuestra CPU es una animadora, no súper significativa, por supuesto, un poco obviamente por encima de los valores estándar que tenemos, pero podemos ver en general cuánto tiempo tardó. Entonces por supuesto, porque realmente no tenemos ningún componente de red, muchas de estas cosas están pasando una tras otra, um, porque realmente no estamos teniendo ningún componente de red esperando. Entonces ahora vamos, en lugar de usar el subproceso, sigamos adelante y usemos el multiprocesamiento. Entonces vamos a decir desde el multiprocesamiento, vamos a importar clase de proceso. Ahora lo bonito del procesamiento y la biblioteca de multiprocesamiento es que en realidad es muy, muy similar en cuanto a cómo está escrito en la biblioteca de subprocesos. Entonces aunque tenemos que hacer realmente es simplemente cambiar estos nombres realmente por legibilidad. Lo único que teníamos que cambiar era esta cosa de aquí. Y ahora vamos a estar usando el multiprocesamiento en su lugar. Entonces lo que vamos a hacer es que lo vamos a hacer, y vamos a actualizar esto a que ya no son hilos numéricos, es número de procesos. Vamos a crear cuatro procesos separados. Entonces los vamos a empezar igual que lo hicimos antes. Vamos a esperar a que terminen igual que lo hicimos antes. Estamos aportando los argumentos aquí tal como lo hicimos antes. Y tampoco ha cambiado la función que estamos llamando. Entonces básicamente estamos haciendo exactamente lo mismo, pero ahora estamos usando el multiprocesamiento. Entonces sigamos adelante y ejecutemos esto. Y voy a abrir de nuevo aquí nuestro monitor de actividades. Y ahora de repente lo puedes ver pico. Y luego un segundo aquí, vamos a tener cuatro procesos. Y así es la cantidad de procesos que realmente hemos creado corriendo. Entonces lo que pasa en este caso es que realmente estamos haciendo uso de más de un núcleo. Por lo que tengo más de un núcleo disponible en mi máquina. Y así por eso, podemos hacer más uso de ella. Ahora obviamente, como podemos ver aquí, son la velocidad no es exactamente proporcional. Están pasando algunos otros factores. Entonces una de las cosas que habrías visto es que la utilización de CPU para los cuatro procesos no fue la misma que la utilización de CPU que tenía uno de los procesos. Entonces creo, además de monitorear esto, dijo alrededor del 80 por ciento para cada uno de los procesos, mientras que la amenaza en realidad casi 99. Algo. Tanto mayor utilización en ese sentido. Obviamente tenemos que dejar espacio para otras cosas que están pasando también, y nuestro sistema operativo, usualmente nos ocupamos de eso, pero podemos ver que aún tenemos una mejora de velocidad. Y la cantidad de mejora de velocidad que podemos obtener de aquí depende mucho del número de núcleos disponibles en nuestra máquina. Entonces, cuantos más núcleos tengamos, más procesos podremos crear muchos procesos, pero cuantos más procesos podamos ejecutar simultáneamente, porque podemos ejecutar cada uno de ellos en un núcleo diferente. Y entonces eso es realmente lo que está pasando en este caso, es cada vez que creamos e iniciamos ese proceso, estamos tomando este intérprete de Python y básicamente estamos iniciando una versión semi fresca en otro proceso para que no estén conflictivo y que no hay bloqueo global de intérprete pasando. Por lo que estos ya no se ven obstaculizados entre este bloqueo global de intérprete. Y así el beneficio que obtenemos de esto es el aceleramiento. Ahora, como hablamos en el muy, muy principio, threading es lo que vamos a estar usando para muy limitado por IO de red. tanto que el multiprocesamiento es lo que queremos hacer para limitado por utilización de CPU o procesos intensivos de CPU, que en este caso no hay red ni espera ni nada. Es solo utilización de CPU, comprobando si un valor está dentro de una lista. Y así a partir de esto podemos ver, obviamente, vamos a estar engendrando un poco mejores resultados de nuestro multiprocesamiento. 17. Colaen multiprocesamiento: Entonces obviamente, podemos mejorar la forma en que estamos haciendo nuestro programa aquí en lugar de rehacer la misma carga de trabajo, algo que generalmente sería más adecuado a función de multiprocesamiento sería dividir nuestra carga de trabajo sobre diferentes segmentos. Entonces digamos que en lugar de rehacer lo mismo para diferentes tiempos, solo queremos distribuir nuestra carga de trabajo. Entonces vamos a tener algunos parámetros extra aquí. Ese va a ser nuestro, sólo lo llamaremos AI ahora mismo y, y luego vamos a tener un número total de procesos. Entonces lo que vamos a hacer aquí es básicamente vamos a hacer uso de su ojo y de nuestro número total de procesos para dividir esto en cubos de igual tamaño. Entonces vamos a empezar con básicamente tener un encuadernado inferior, que va a ser yo por 10 a la 8. Y entonces también queremos tener un encuadernado superior que va a estar apagado. Ni siquiera necesitamos el número total de procesos aquí, que va a ser yo más una vez 10 a la 8. E incluso podemos quitarle este valor, extraído un abstracto en otra variable. Entonces vamos a decir número máximo para checar dos va a ser de diez a octavo. Y así entonces vamos a empezar desde nuestro margen inferior. Vamos a ir a nuestro atado superior. Entonces vamos a decir de I en rango inferior a superior. Y así por ejemplo, si tenemos 0 aquí, vamos a pasar de 0 a básicamente, bueno, una vez esto. Por lo que sí necesitamos una serie de procesos. Ahí es donde entró. Número de procesos. Y sólo vamos a dividir esto aquí por el número de procesos y convertir todo esto en un entero. Dado que nuestra función de rango aquí quiere que utilicemos un entero. Entonces vamos a pasar de, el primer paso va a ser de 0 a una veces este número dividido por el número de procesos. Entonces va a ser 1 más de 4 más de 10 millones de un 100 millones, que van a ser de 25 millones. Y luego a paso cuando yo sea uno, vamos a pasar de 25 millones a 50 millones. Entonces van a ser 2 veces 25 millones. Y entonces nos vamos a ir y estos pasos. De acuerdo, entonces el ojo que ya tenemos aquí, yo soy de nuestro ojo aquí, el número de procesos que también ya tienes, porque eso es lo que estamos definiendo en este bucle de rango aquí. Entonces lo que estamos haciendo en este caso es, bueno, ahora mismo lo acabamos de reescribir para que sea un programa más al menos semirealista para entender o para ver cómo podemos simplemente dividir la carga de trabajo. Y si volvemos a ejecutar esto, entonces obviamente en nuestro monitoreo de actividad o segundo, vamos a ver tu carga de CPU, carga aquí pico. Pero obviamente va a ser mucho más corto porque no estamos haciendo lo mismo cuatro veces, sino en cambio, si dividimos esta operación en cuatro procesos separados. Entonces sí, Entonces generalmente Aunque, no sólo queremos tener esta información, sino que también queremos usarla. Y así hemos visto anteriormente mucho que en realidad podemos usar la cola para transmitir información. Y podemos hacer algo similar aquí. Todavía podemos usar nuestra cola y podemos crear una instancia de la clase fuera. Y también podemos proporcionar eso como insumo, como tenemos aquí. Y así tal vez la información que queremos transmitir es un cada cubo, cuántos valores hay en nuestra lista y cuántos valores no están en nuestra lista. Entonces tendremos una variable que tiene número de hits, solo va a ser 0. Y entonces sólo vamos a decir si x, vamos a incrementar o número de hits por uno. Y luego al final, vamos a poner este valor en la cola junto con inferior, superior, y una serie de hits. Entonces de esa manera, podemos hacer algo de procesamiento. En realidad podemos hacer uso de la información de los resultados que estamos procesando. Por lo que sólo vamos a comprobar en cada rango de cubos cuántas de nuestras variables están en realidad dentro de esta lista. Vamos a poner esto en cola. Y luego aquí hacia el final, también queremos simplemente poner hecho en la cola. Y luego vamos a tener sólo un bucle while simple que va a decir mientras. Y entonces vamos a decir que v es igual a Q dot consigue. Si v es igual a hecho, vamos a estallar. De lo contrario tenemos nuestro menor o mayor número de hits y Veeam. Y vamos a decir entre inferior y superior, tenemos número de valores de hits en la lista. De acuerdo, así que vamos a correr esto una vez más. Y de nuevo en nuestro gráfico de CPU, podemos ver aquí la pequeña espiga. Por lo que podemos ver ahora tenemos alguna buena información. Entonces entre, en este caso, 0 a 25 millones, tenemos tres valores en la lista, obviamente, porque tenemos 123 en la lista. Y luego entre los otros, no tenemos mucha información. Entonces el punto de esta lección es que podemos ver todavía podemos seguir usando Q de la misma manera que lo usabas antes, pero poder pasar información entre y procesos o diferentes hilos como lo hacíamos antes. Pero ahora va a ser entre diferentes procesos y usar eso ahí dentro. Y ojalá, se pueda ver que podemos usar procesos para básicamente extender la carga de trabajo. Obviamente, el ejemplo que tenemos aquí es un ejemplo muy simplificado. Pero aún podemos ahorrar una cantidad decente de tiempo en lugar de usar su ejecución en serie simplemente haciendo todo al mismo tiempo. O incluso enhebrando donde básicamente va a ser lo mismo porque somos tan intensivos en CPU, pudimos hacer más uso del número de núcleos que tenemos disponibles en nuestra máquina. Y en realidad hacer uso de más de nuestra CPU para ayudarnos a completar estos cálculos más rápido. Ahora bien, esto es importante para uno, si estás ejecutando cosas en tu propia máquina, solo quería terminar más rápido y tienes muchos recursos que solo están sentados inactivos. Esto obviamente puede ayudarte a hablar de programas, pero también si estás implementando aplicaciones y tienes recursos adicionales de CPU disponibles, si no estás haciendo uso de esos recursos, solo se van a quedar inactivo y vas a pagar por ellos, pero en realidad no vas a estar haciendo uso de ellos. Entonces obviamente depende, ya sabes, si tienes un solo núcleo en lo que estés implementando, entonces este multiprocesamiento no va a ayudar mucho porque todavía solo tienes un núcleo disponible. Pero si terminas teniendo una máquina o teniendo una implementación donde tienes varios núcleos de CPU disponibles. Quieres asegurarte de que puedas hacer el mejor uso de ellos. 18. Piscina de multiprocesamiento: Muy bien, entonces, hasta ahora hemos visto cómo podemos usar el multiprocesamiento para ayudarnos a distribuir parte de nuestro trabajo entre diferentes CPU. Y obviamente el patrón que estamos viendo aquí es muy similar al patrón de enhebrado con el que habíamos entrado en detalle previamente. Y probablemente ya puedas adivinar. Pero la forma en que hicimos herencia de clases con threading y todo lo que hicimos cuando creamos nuestros trabajadores de subprocesos, podemos hacer lo mismo con la clase de proceso. Por lo que podemos heredar de la clase de proceso y podemos tener un inicio y unir métodos definidos dentro así como sus métodos de ejecución. Y básicamente podemos acercarnos a crear un programa multiprocesamiento alrededor de clases de multiprocesamiento que todos inhiben y heredan de esta clase de proceso, igual que hicimos cuando pasamos por todas las cosas de subprocesos. Y no vamos a bajar por esa ruta porque ya lo hicimos para enhebrar. Y obviamente, habría muchas cosas repetidas que estaríamos bajando. Entonces solo ten en cuenta que lo que hicimos para enhebrar y los enfoques que usamos en la sintaxis casi va a ser idéntico al multiprocesamiento, excepto que en lugar de usar la clase de subprocesos, en su lugar vas a estar usando el proceso clase aquí. Entonces lo que quiero mostrarles ahora sin embargo, es a veces cuando escribimos un programa de subprocesos, anteriormente había mucha red IO y puede tener sentido tener estos como intrincadamente desarrollar programas para que podamos usar cues para pasar todo el estado en internamente. Y mientras que un hilos diferentes son responsables diferentes servicios que todo tipo de trato con la red cargan ahí. Pero a veces cuando estamos haciendo multiprocesamiento, como que tenemos nuestro flujo de trabajo cortado y en lugar de como reescribir todo, solo sabemos, oh, aquí hay algo que quiero optimizar. Y obviamente podemos hacer lo mismo con el threading si tenemos como un pequeño componente donde estamos como, oh, aquí hay un montón de cosas de red que básicamente puedo optimizar y sabes, lugar de esperar y serializado, Yo solo puedo hacer todas estas cosas y básicamente la mitad de todos los hilos para que la espera pase casi simultáneamente. Pero para el procesamiento ahora solo quiero enfocarme en ese componente. Y en lugar de desovar los procesos individuales como este, usando colas para transmitir información, solo quiero simplificar mucho esta cosa. Y lo que quiero hacer en cambio es que en última instancia quiero llegar al punto en el que sólo puedo pasar nuestros límites inferior y superior. Y básicamente tipo de acaba de distribuir esta obra para nosotros y luego simplemente conseguir como un centro de valor de retorno. Saca la q aquí para sacar a esta Q. Entonces no quiero usar tacos ni nada. Básicamente, solo quiero tener una variable que pueda tener como una variable de resultado que va a decir algo como 30, 0, 0, y para que pueda simplemente seguir usando eso. Ahora antes de hacer esto, empecemos con algo más sencillo. Simplemente vamos a empezar con el pool básico de procesamiento y vamos a tener una función mucho más simple donde sólo vamos a cuadrar todo. Entonces vamos a volver mucho a lo básico, de vuelta a una especie de ejemplos mucho más sencillos. Y solo vamos a tener una función simple primero que nos permita cuadrar todo. Porque en última instancia, una vez que podamos hacer eso, entonces podemos hacer cosas más complicadas en la sintaxis, punto difiere un poco de cómo estamos usando el pool, razón por la cual quiero empezar con este ejemplo muy simple primero así que sólo podemos ver cómo funciona esto y cómo podemos obtener ese resultado. Entonces podemos ir a actualizar o sintaxis para que podamos hacer lo aún no súper complicado, pero obviamente pasando más variables y cosas que teníamos antes. Entonces en lugar de usar el proceso, ahora vamos a usar la clase pool. Ahora con la clase pool, podemos inicializarla usando el contexto. Entonces con alberca como alberca o como P o lo que quieras tira bastante agradable porque, ya sabes, obviamente es bastante específico. Podemos ser más específicos y decir como el multiprocesamiento. Bastante seguro que hay un tipográfico aquí en alguna parte. Procesando alberca. O si no queremos escribir todo así, sólo podemos escribir como y la gente para ser un poco más específicos. Pero básicamente solo vamos a inicializar esta clase de pool y luego usarla dentro del contexto. Por lo que ahora tenemos a nuestra disposición un conjunto de procesos que podemos utilizar. Entonces básicamente, y nos meteremos en esto en un segundo. Pero en realidad podemos definir aquí el número de procesos que queremos tener disponibles en nuestra alberca. Por ejemplo, ¿quién puso el número dos? Y aquí, eso significa que tenemos el potencial, pero no necesariamente necesitamos usarlo de dos procesos que están disponibles para nosotros y podemos seguir realizando operaciones y básicamente tomando esos procesos. Pero una vez que todos esos procesos son retirados de la alberca, ya no están disponibles para nosotros y básicamente tenemos que esperar hasta que el proceso sea devuelto a la alberca para que la siguiente operación pueda luego usarlo. Entonces otra vez con nosotros, estamos básicamente, solo van a crear como un pequeño, puedes imaginarlo como un pequeño cubo. Y en ese cubo tenemos una serie de artículos disponibles. Y podemos sacar de ese cubo. Y una vez que ese cubo esté vacío, tenemos que esperar hasta que, ya sabes, algo, alguien vuelva a meter el artículo que sacaron. Y luego una vez que algo vuelva a estar en el cubo, podemos sacarlo de nuevo. Entonces en este momento tenemos un pool de tamaño dos, lo que significa que tenemos dos procesos disponibles para nosotros que podemos usar, lo que esencialmente significa que podemos usar para curso, ya que cada proceso va a estar desovar un nuevo núcleo. Entonces lo que vamos a hacer aquí es que vamos a usar un nuevo método. Vamos a usar nuestro cool de multiprocesamiento. Y en él vamos a utilizar este método de mapa. Y aquí vamos a poner la función que queremos usar. Entonces esa va a ser la plaza. Y entonces también vamos a proporcionar aquí nuestras variables de entrada. Y vamos a guardar todo esto en una variable de resultado. Y podemos sacar el componente de tiempo aquí, ya que ya no estamos usando eso. Y vamos a seguir adelante e imprimir nuestro resultado. Esto no puede simplemente ejecutar nuestra función principal. ¿ De acuerdo? Entonces básicamente, obtuvimos exactamente lo que esperábamos, que es que tomamos nuestra lista de entrada aquí y obtuvimos el cuadrado de cada valor. Pero ahora lo interesante que tenemos con nosotros es que somos capaces de usar este pool y somos capaces de aplicar este método de mapa ahí. Y sólo vamos a hacerlo, básicamente va a aplicar esto a cada componente. Entonces va a estar iterando a través de esos uno por uno. Pero vamos a recuperar la misma estructura, pero con nuestros valores internamente actualizados, pesar de que solo estamos operando en una variable, podemos devolver esto y básicamente obtener nuestro nuevo resultado, que va a ser nuestra lista original aquí en nuestras listas de comparación en este punto. Pero va a estar al cuadrado. Por lo que cada valor de aquí se va a cuadrar. Ahora bien, este valor, obviamente, puede depender de la máquina que te estás quedando sin. En ocasiones solo puedes usar una CPU porque solo tienes una disponible. En ocasiones puedes cuatro o seis u ocho o 16 o por muchos que tengas disponibles en tu máquina. Entonces, ¿cómo podemos hacer que este poquito mejore para que en realidad pueda adaptarse a la máquina en la que se está ejecutando. Bueno, está esta función genial que podemos importar llamada recuento de CPU. Y el recuento de CPU, como habrás adivinado, ella, sólo nos va a dar el número de CPUs que tenemos disponibles. Entonces lo que puedes hacer es decir número de CPU disponibles. Simplemente va a ser, y sólo vamos a invocar nuestro conteo de CPU. Entonces por tan solo imprimir esto. Y se puede ver mi máquina por la que se va a disparar ya que tengo cuatro carbonos disponibles. Pero esto podría diferir dependiendo de la máquina en la que se esté ejecutando. Pero tal vez el número de CPU que quieres usar va a ser uno menos que el número de CPUs disponibles. Porque si estás usando todos tus núcleos, entonces hay, ya sabes, todo se va a usar. Y así puede que en realidad no haya suficientes CPU para que otras cosas sigan adelante. Otros procesos del sistema operativo, por ejemplo. Entonces generalmente lo que quieres hacer es decir que el número de CPU a usar va a ser nuestro recuento de CPU menos uno. Pero en el caso en que en realidad solo tengamos un núcleo, queremos decir, está bien, bueno va a ser el mínimo. Por lo que sólo me van a pensar el máximo entre uno y el número de CPUs disponibles minús1. Y entonces podemos usar esto aquí. Entonces en este caso, por ejemplo, puedo imprimir número de CPU utilizadas. Y ahora vamos a mostrar tres, ya que va a ser el valor máximo entre 14 menos uno, que es tres. Por lo que el valor máximo entre estos dos va a ser de tres. Pero en el caso en que solo tengamos una CPU, así que estamos, este valor es uno. En cambio vamos a estar usando el predeterminado. Ya que obviamente todavía queríamos hacer algo. Entonces de esta manera podemos decir, está bien, así que dependiendo de la máquina en la que nos estamos ejecutando, podemos ver el número de CPU disponibles. Y entonces podemos tener nuestro ser mancomunado de ese tamaño, de que hay muchos procesos disponibles para que podamos sacar de. Y luego podemos mapear en estos objetos de entrada en la función que queremos usar para esto y luego obtener esos simplemente valor de retorno realmente agradable que simplemente podemos seguir usando. Entonces en lugar de tener que hacer este cereal. Entonces estamos iterando y estamos diciendo k para I en rango de lo largo o lista que sea. Y luego vamos a la plaza y vamos a poner eso en una nueva lista. Vamos a, vamos a actualizar nuestro valor, cualquiera que sea, y luego seguir usando así. Podemos simplemente usar este pool de multiprocesamiento y básicamente mapear estos valores a nuestra función y simplemente obtener los valores de retorno actualizados para que podamos seguir usando esto. Porque estos, estas disfunción pueden ocurrir en paralelo porque obviamente no depende de nada más a su alrededor. Y así con esto, somos capaces de escalar, usar esto para acelerar muy rápidamente ciertas partes de nuestro código que no necesariamente necesitan una refactorización completa, como la forma en que vimos con el subproceso. Pero ya sabes, sólo una pequeña línea aquí podría ayudarnos en realidad a distribuir mucho el trabajo. Y entonces sólo podemos seguir adelante a nuestra manera regular. 19. Mapa de poetas multiprocesado: Está bien, Así que ahora probablemente te estés preguntando, bien, bueno, ¿cómo puedo pasar múltiples argumentos? ¿ Cómo puedo hacer algo así? Y quiero hacer x, pero quiero hacer x al poder de y así. Y quiero decir, ya sabes, nuestro nuevo valor de poder va a ser tres propios. Es posible que hayas pensado eso. Yo sólo voy a poner ese argumento extra aquí dentro y eso se va a cuidar de ello. Desgraciadamente no. Y te mostraré lo que va a pasar, pero tengo que deshacer esto. De lo contrario nos vamos a encontrar un tema diferente aquí. Pero si ejecutamos esto y miramos la salida, ya no estamos pasando ahora los valores individuales dentro de la lista aquí, sino que estamos pasando la lista misma. Entonces estamos iterando sobre cada elemento aquí dentro y pasando eso como entrada. Entonces si ponemos y aquí, no vamos a conseguir los resultados que queremos sin importar si lo tenemos. Y ver aquí, ¿estamos todavía llamando, no lo estamos imprimiendo porque nuestra función en realidad ya está fallando porque nos falta un argumento adicional para por qué. Y aunque hagamos algo así, ninguno de estos va a funcionar para nosotros. Entonces, ¿cómo podemos proporcionar este parámetro extra aquí? Bueno, vamos a usar un paquete Python llamado func tools, que viene ya preinstalado con Python. Y desde aquí vamos a importar un método llamado parcial. Ahora parcial nos va a permitir crear funciones parcialmente definidas. Por lo que podemos llamarlos parcialmente, pero no se les va a llamar del todo. Pero ya podemos proporcionarnos algunos de los parámetros antemano y luego podemos perderlo más adelante. Ahora para hacer esto, porque la forma en que vamos a estar proporcionando parámetros va a ser en un orden específico. Y así queremos asegurarnos de que dejamos el parámetro que va a ser básicamente la variable que va a cambiar hasta el final. Entonces voy a crear una función parcial usando el método parcial. Voy a tener esta plaza aquí. Y el valor que quiero para y va a ser nuestro poder aquí. Ahora puedo usar esta función parcial en el método de mapa y puedo quitarle todo esto. Ahora nuestro mapa sólo va a iterar sobre este uno por uno, y aquí va a llamar a esta función. Esta función ya está parcialmente definida llamando a tomar el método de raíz cuadrada y proporcionando este primer parámetro, potencia como esta. Entonces si ejecutamos esto ahora, nos vamos a poner todo en cubos, ya que eso es lo que tenemos aquí. Obviamente, podemos cambiar esto todo al poder de cuatro, como tenemos aquí. Y también podemos extender esto para parámetros extra como adición, componente. Y digamos que queremos tener todo al poder de tres. Y luego queremos tener algún componente adicional, y eso va a ser 2. Nosotros vamos a proporcionar eso aquí. Por lo que sólo vamos a sumar eso al resultado al final. Entonces si ejecuto esto, entonces vamos a conseguir todo en cubos y luego vamos a tener un plus dos que viene de este erratico de aquí. Por lo que podemos ver si queremos usar el método de mapa y queremos tener variables extra aquí. No podemos simplemente desafortunadamente convertir esto en una tupla o una lista y luego pensar que, Oh sí, todo va a recorrer eso. Desafortunadamente, así no es como funciona el método de mapa con pool de multiprocesamiento. Pero si tenemos variables fijas que ya hemos definido de antemano que sólo queremos proporcionar aquí. Y nuestro último componente aquí va a ser lo que va a cambiar. Entonces en realidad podemos usar este método parcial de las herramientas funk. Y aquí podemos definir parcialmente nuestra función. Y entonces podemos llenarlo con los diferentes componentes que tenemos aquí para tipo de llamar a la función y es manera completa y realmente conseguir los resultados que queremos mientras ya tenemos algunos de los argumentos pasados. 20. Multiprocesado varios Arguments variados: Muy bien, así que anteriormente hemos visto que podríamos proporcionar argumentos adicionales usando este método parcial en nuestras herramientas func, una biblioteca aquí que hemos importado. Y pudimos definir parcialmente funciones o proporcionar parcialmente los componentes de funciones. Y entonces podemos usar nuestro método de mapa aquí para especie de proporcionar ese componente restante. Pero y si no queremos o no tenemos componentes fijos, pero en cambio queremos tener alguna entidad diferente, por ejemplo, alguna impotente. Y aquí lo que queremos hacer es tener aquí el primer elemento, por ejemplo, el poder para el segundo al poder 5 y el tercero al poder de seis. Por lo que ya sabemos lo que queremos proporcionar. ¿ Cómo podemos hacer esto de una manera que no es así, sino idealmente sólo poder proveer eso directamente y realizar esos cálculos. Entonces voy a hacer algo de limpieza rápida aquí arriba, quitar esto, y también hacer sólo alguna reorganización de nuestros parámetros de función. Sólo tenerlo un poquito más debería ser mentir. Un poco más fácil de ver. Y tampoco necesitamos esta definición parcial de función aquí. Entonces lo que queremos hacer es, o lo que podemos hacer es usar un método llamado mapa estelar. Ahora en nuestro mapa estelar, podemos proporcionar una entrada aquí que tenga lo siguiente, que se vea así. Y luego en el interior podemos proporcionar elementos adicionales que podemos iterar si queremos. Y todos estos elementos, entonces podemos pasar como parámetros individuales a nuestra función. Entonces por ejemplo, en nuestro caso, lo que queríamos hacer es mientras un primer elemento que queremos pasar sería 1 y 4, ya que ese va a ser nuestro x e y El segundo va a ser 25, y luego el tercero aquí es va a ser 36, ya que queremos proporcionar estos dos juntos y luego proporcionarlos como nuestros parámetros x y nuestro y. Y así si proporcionamos esto como insumo, entonces básicamente lo que vamos a conseguir es la ejecución así. Y obviamente estamos usando quién aún el pool de multiprocesamiento. Por lo que vamos a poder usar diferentes colores para ayudarnos a hacer esto. Entonces realmente lo que necesitamos hacer en este momento es que necesitamos unirnos a estas dos listas juntas de una manera para que podamos conseguir este formato aquí. Y entonces podemos proporcionar eso como insumo. Entonces vamos a tener nuestra lista preparada, que sólo va a ser lista vacía con la que vamos a empezar. Por lo que sólo vamos a iterar sobre la longitud de esta lista. Y así nuestros elementos que queremos sumar aquí sólo van a ser, queremos tener aquí, nuestro primer elemento siempre va a venir de nuestra lista de comparación. Va a ser el primer elemento aquí. Y el segundo elemento que queremos, va a venir de nuestra lista de poder, que podemos poner 0. Queremos el ith componente. Y así podemos imprimir la última vez que vamos a insertar algunas listas para usar como entrada. Sólo va a ser esto. Y entonces podemos ejecutar esto. Y entonces realmente podremos proporcionar cada uno de los elementos dentro como uno de los parámetros aquí dentro. Entonces sigamos adelante y ejecutemos este bucle. Tengo un tipografía aquí. Y también me olvidé de actualizar. Esto levanta aquí. Entonces intentemos eso una vez más. Ahí vamos. Entonces esta es la lista que estamos usando como entrada. Y podemos ver que nuestra x y nuestra y. entonces estos son nuestros parámetros de función que estamos pasando. Entonces esta va a ser tu x y nuestra y, nuestra X y nuestra Y, o X y nuestra Y. Entonces estamos haciendo uno al poder cuatro, que es 12 al poder de cinco, que debe ser 32, y 3 al poder de seis, que debe ser 729. Entonces podemos ver que usando un mapa estelar, en realidad somos capaces de proporcionar múltiples parámetros de entrada, sobre todo si, sabes que estos van a estar cambiando. Es solo importante asegurarnos de que tenemos este tipo de estructuras para que podamos pasar estos. Y entonces los elementos o los valores que estamos pasando a nuestra función van a estar en el orden en que tengamos los parámetros en nuestra función aquí. Y así a través de esta forma, en realidad somos capaces de pasar en múltiples parámetros. Entonces el bate, no necesitamos usar estas definiciones funcionales parciales, de función si más de una de nuestras variables está variando. 21. Elementos de comprobación de multiprocesado en la lista de ciertos Rangos: Muy bien, Así que por fin volvamos a nuestra función inicial un poco más intensiva de CPU que estábamos usando, que sólo va a estar comprobando si un valor o cuántos valores en nuestra lista de comparación están en realidad dentro de un rango específico. Por lo que se puede decir, llamar a esto por ejemplo, comprobar número de valores en rango. Y entonces vamos a tener aquí va a ser nuestra lista de comparación. Y aquí vamos a tener nuestros límites inferior y superior. Y luego queremos rastrear los aciertos numéricos. Y entonces queremos decir para yo en rango de menor a nuestro tope superior. Si los ojos y nuestra lista aquí. Nosotros sólo queremos aumentar esto en uno. Entonces sí, nos falta un yo aquí y al final sólo queremos devolver el número de hits. Entonces nuevamente, el punto de esta función no es realmente hacer nada más excepto ser algo de alguna manera, para que nosotros simulemos solo un poquito más de una tarea computacionalmente intensiva porque se va a toma un poco de tiempo para calcular esto. Entonces los diferentes rangos inferior y superior que vamos a tener. Y si queremos, sólo podemos especificar estas reglas de rango. Llamemos a estos límites inferior y superior. Y por supuesto podemos generar estos dos con como un poco for-loop. Pero en realidad si sólo nos estamos dividiendo en cuatro, básicamente se puede ver lo que estamos haciendo es ir de 0 a 25 millones. Entonces van a ser diez al poder de seis. Y luego vamos a pasar de 25 millones a 50 millones veces diez al poder de seis. Y entonces sólo voy a copiar esto. Y vamos a pasar de 50 millones a 75 millones. Y por último, queremos pasar de 75 millones a 100 millones. Entonces estos van a ser nuestros límites inferior y superior. Ahora por supuesto, necesitamos meterlo en este tipo de formato. Pero en cambio lo que queremos en este caso es básicamente queremos nuestras listas de comparación para el primer valor de entrada. Y entonces queremos nuestro inferior y nuestro superior aquí. Y entonces queríamos hacer estos o los otros también. Por lo que todavía tenemos que hacer como un poco de unirnos como lo hicimos aquí. Pero como aquí no tenemos muchos valores, sólo estoy siendo más fácil de especie de poner estos cuatro valores y a mano. Pero obviamente podemos escribir un poco for loop para poblar esta lista también para nosotros, sobre todo si quisieras gustarte 50 o un 100 o incluso como 10 o 20 saldo diferente. Sí, de todos modos, así que de nuevo sólo necesitamos preparar nuestra lista. Por lo que vamos a utilizar nuestra lista de comparación aquí. Pero en lugar de iterar sobre esta longitud, básicamente vamos a agregar esto como uno de los elementos aquí. Y así el número de diferentes valores de entrada que vamos a tener en realidad van a ser las listas, la longitud de esta lista. Por lo que queremos iterar sobre la longitud de esta lista. Aquí queremos añadir la lista de comparación completa. Y también queremos sumar los componentes individuales. Entonces va a ser nuestro primer y nuestro segundo valor aquí. Y luego vamos a proporcionar esto como insumo para hacer nuestros cálculos. Entonces otra vez, lo que estamos haciendo es que estamos tomando esta lista y básicamente estamos teniendo nuestra nueva lista preparada, que va a verse así y así. Entonces eso es justo lo que estamos haciendo aquí. Y entonces este componente aquí va a ser nuestro primer insumo aquí, que va a ser una lista. Y luego los otros van a ser nuestros límites inferior y superior. Entonces voy a deshacer esto obviamente porque eso es lo que este pequeño bucle aquí como cuatro. Y entonces sigamos adelante y ejecutemos esto. Y así podemos ver estos van a ser nuestros parámetros de entrada aquí. Cada uno de estos, como tenemos en los argumentos de función, esta va a ser nuestra lista de comparación, nuestros límites inferior y superior. Y así podemos ver obviamente en el primer rango tenemos tres elementos que están contenidos lado porque sus números son 123. Y luego en los otros iban todos a tener 0. Entonces esto es una especie de ir círculo completo de vuelta a lo que empezamos con cuatro, lo siento, ejemplo para el multiprocesamiento para tipo de ayudarnos a hacer esto. Y ahora podemos usar nuestro método de inicio en este caso para proporcionar estos múltiples argumentos de entrada como tenemos aquí. Ahora, una cosa que podemos hacer en realidad para simplificar un poco la sintaxis, es en lugar de enumerar las listas así. En cambio lo que podemos hacer es simplemente usar este pequeño astérix. Y lo que eso va a hacer es que va a desempacar todos los valores aquí dentro. Para que veas si vuelvo a ejecutar esto, vamos a obtener exactamente los mismos resultados. La única diferencia es que yo tenga que hacer referencia a cada uno de estos componentes individuales como lo hicimos aquí. Esta estrella básicamente la va a desempaquetar y va a tomar todos estos y proporcionarlos como valores de entrada adicionales uno a la vez, siguiendo exactamente en el orden en que los tenemos aquí. Entonces esto es solo un poco de taquigrafía que puedo usar en lugar de usar esto porque quiero conseguir todos los elementos. Pero si tengo como, ya sabes, 10 o 20 o 15, como si se va a hacer más largo y va a ser tedioso. Y entonces realmente lo que quiero hacer es que solo quiero tener todos estos valores aquí, pero no los quiero en un formato de tupla como este. Yo sólo quiero todos los elementos individuales uno tras otro. Y la forma en que puedo hacer eso es usando la estrella, que va a proporcionar cada uno de estos elementos dentro como valores individuales aquí. Entonces esto es sólo una taquigrafía para especie de mantener eso más limpio y también hacer que sea un poco más rápido para escribir. 22. Introducción a los programas asíncronos: De acuerdo, así que ahora empecemos a echar un vistazo a los programas asíncronos o cómo podemos escribir un programa asíncrono. Y esta va a ser nuestra tercera opción que tenemos para la concurrencia. Y notarás un punto. Probablemente se vaya a ver similar al subproceso, aunque de nuevo diferente porque con programas asíncronos, solo tenemos un hilo que se está ejecutando, y también solo tenemos un proceso. Entonces sigamos adelante y solo pongámonos en ello y veamos qué pasa. Entonces lo primero que vamos a hacer es que vamos a importar IO asíncrono, que sólo nos va a ayudar con todo esto. Ahora estoy en Python versión 3.7 y te recomiendo que también estés trabajando en al menos la versión 3.7 de Python. Pero también obviamente por supuesto, si estás en una versión posterior de Python, será mejor sólo porque hasta este punto, la biblioteca asíncrona ha sido un poco no experimental, pero ha estado cambiando mucho. Y en este punto parece haber de un estado conjunto con cómo está funcionando. Por lo que en general solo recomendaría, asegúrate de que estás usando una versión posterior de Python si quieres. O al menos Python 3.7, que es de nuevo lo que estoy en este momento. Por lo que podemos importar IO asíncrono y que debería ser un paquete Python predeterminado. Y entonces podemos empezar a definir nuestra primera función asíncrona. Por lo que podemos hacer esto simplemente teniendo una función regular. Por ejemplo, si queremos tener algún tipo de función de sueño donde todo lo que hacemos aquí es dormir, digamos cinco segundos. Si en cambio queremos hacer esto de forma asíncrona, entonces pondríamos delante de aquí la palabra clave asíncrona. Y luego aquí en lugar de usar el sueño temporizado, en realidad usaríamos un método de sueño de sincronización iOS. Y hablaremos un poco más sobre el razonamiento en tan solo un segundo. Pero básicamente lo que obtenemos de esto, así es como vamos a definir una función asíncrona. Ahora tenemos que hacer una cosa más aquí, que es que realmente necesitamos esperar esta función o esta co-rutina es en realidad lo que se llama. Y realmente lo que está pasando aquí. Y todo el proceso de usar la ejecución asíncrona y Python es, y veremos cómo hacerlo en un segundo. Pero empezamos algo llamado bucle de eventos. Y luego podemos agregar, empezar a agregar tareas o programar tareas con este bucle de eventos. Y luego dentro de ese bucle de eventos tendrá objetos llamados o tendrán cosas llamadas futuros. Y estos futuros básicamente representan algo que aún no ha regresado, pero de esto va a salir algo. Entonces esto puede sonar un poco confuso, pero generalmente ¿qué sucede si programamos varias funciones asíncronas? Cada uno de ellos brindará un futuro que en algún momento y terminarán o llegarán a algún tipo de punto de control. Y a partir de ese momento, podemos entonces hacer lo siguiente con esa co-rutina. Todo lo que hemos definido aquí, esto generalmente se le conoce como una co-rutina. Y son las cosas que agregaremos y programaremos en nuestros bucles de eventos. Ahora, a medida que seguimos codificando, ojalá esto se vuelva un poco más intuitivo y no nos perdamos tanto en toda la sintaxis de todo. Pero obviamente, porque no estamos pasando por cosas asíncronas, es importante solo mencionar y platicar a través de algunas de estas palabras clave y el principio, pero también a medida que estamos continuando. Entonces si quisiéramos ejecutar esto, si solo llamábamos y en realidad cambiemos el nombre de esto a sueño asincrónico. Si acabamos de llamar a un sueño fregadero. Duerme así. Desafortunadamente, en realidad no se va a ejecutar. Aquí vamos a conseguir un error, que básicamente está relacionado con eso. Bueno, por una dice que nunca se esperó el Coubertin, que es lo que tenemos aquí. Pero incluso si agregamos esta palabra clave await, todavía no va a funcionar porque no tenemos un bucle de eventos corriendo en este momento el cual está consumiendo todo esto. Y aparte de eso, en realidad no podemos usar la palabra clave await fuera de una función que no es asíncrona def. Entonces, ¿cómo podemos conseguir que esta cosa funcione? ¿ Cómo podemos conseguir que estos huesos desnudos vayan? Entonces vamos a crear una nueva función, que va a ser nuestra función principal, que también vamos a definir con def asíncrona. Y lo que vamos a hacer aquí es que vamos a esperar la respuesta de nuestro sueño asincrónico. Ahora, las palabras clave aguardan aquí porque tenemos este bucle de eventos y podemos tener varias co-rutina diferentes programadas ahí para correr. Básicamente lo que hace esta palabra clave espera es que le devuelve el control a nuestro bucle de eventos para continuar con otras cosas. Entonces básicamente le dice al programa que en este punto estamos, estamos esperando una respuesta y hasta que tengamos esa respuesta o hasta que tengamos algo aquí que necesitamos continuar. Realmente no tiene sentido darme todos los recursos porque no hay nada que pueda hacer hasta conseguir esto. Entonces ese es generalmente el punto de un peso. Pero aunque tengamos esto, todavía no podemos llamar al principal Hulk. Entonces, ¿cómo puedes conseguir que el principal se ejecute? Entonces lo que podemos hacer es que podemos usar este método asíncrono IO dot run. Y aquí vamos a poner la principal co-rutina que queremos correr. Y esto básicamente iniciará el bucle de eventos para nosotros. Y se iniciará el consumo del bucle de eventos y básicamente se ocupará de todo el proceso para nosotros. Hay otros métodos. Por ejemplo, puede obtener un bucle de eventos en ejecución y puede ejecutarse hasta su finalización o estas otras cosas que son más específicas del bucle de eventos. Pero realmente solo usar asíncrono IO dot Ron se encargará de toda esta gestión por ti y realmente no necesitas preocuparte por ninguna de las cosas de nivel inferior. Entonces este aquí va a ser nuestro punto de entrada. Ahora una cosa importante a tener en cuenta es que solo podemos tener un bucle de evento en ejecución por hilo. Y por defecto sólo vamos a estar ejecutando esto en un núcleo y un solo hilo. Entonces básicamente lo que eso significa es que solo vamos a tener una llamada asíncrona IO dot, que va a ser el punto de entrada a nuestro programa. Y por supuesto, podemos envolver esto en el if name es igual a main. Um, así que por ejecutar el archivo principal aquí, entonces vamos a empezar con puede entrar en este bucle de eventos. Está bien, así que sigamos adelante y probemos esto ahora. Entonces estamos ejecutando el programa y todo lo que estamos haciendo es dormir asincrónicamente durante cinco segundos. Pero obviamente no está pasando mucho más en este punto porque sólo estamos haciendo una cosa. E incluso si estamos devolviendo el control al bucle de eventos, que es lo que estamos haciendo aquí. No hay nada más corriendo, no hay nada más pasando, así que no hay nada más que seguir trabajando durante este tiempo. Entonces vamos a agregar una segunda función ahora, que va a ser una función asíncrona para imprimir hola. Y todo lo que esto va a hacer es que va a imprimir como el nombre sugiere. Hola. Muy bien, entonces, ¿qué pasa ahora? Si programamos como aquí? Y luego pongamos algo de impresión extra aquí solo para ver dónde estamos en nuestro programa. Entonces lo vas a decir antes de dormir. Y luego podemos poner otra huella después. Aquí. Sólo vamos a estar después de dormir. Muy bien, entonces, ¿qué está pasando? Tenemos, bueno, flotamos punto de entrada. Entonces estamos iniciando básicamente el bucle de eventos y estamos iniciando la x o la programación de su principal co-rutina. Después entramos en esta ruta principal co-rutina aquí. Y ahora vamos a nuestra primera línea la cual va a estar esperando la respuesta de esta corutina de sueño asíncrona que tenemos aquí. Una vez que entramos aquí, imprimimos antes de dormir, y luego tenemos esta llamada esperada. Entonces lo que pasa con la llamada await es la forma en que la llamada no está bloqueando. Permite la ejecución de otras rutinas co. No obstante, sí detiene la ejecución de ir más abajo en esta función. Entonces, y si ejecutamos esto, notarás que entraríamos en esta función y luego llamamos antes de dormir. Y luego dormimos cinco segundos. Y luego entramos en el después del sueño. Y sólo entonces pasamos a la segunda declaración aquí. Desafortunadamente con esto, no podemos saltarnos e ir a lo siguiente. Esta espera es básicamente un punto de ruptura en nuestra co-rutina, en nuestra ejecución de programas como específicamente en esta función están en esta co-rutina. Y esto es un poco donde nos detenemos momentáneamente para su ejecución. Y básicamente dice, o la función o la co-rutina en este punto dice, no necesito control ahora mismo. Estoy esperando una respuesta. Siéntete libre de seguir haciendo en otras cosas. Y entonces nuestro bucle de eventos puede continuar y hacer otras cosas. Y siempre que esta función esté lista, puede dar una señal diciendo: Oye, estoy listo para continuar. Y luego se le puede devolver el control. Pero debido a que solo tenemos una co-rutina principal corriendo, y dentro de éstas, llamamos rutinas tumorales Cole. Todos estos siguen ejecutándose secuencialmente y no hay no hay múltiples rutinas co programadas al mismo tiempo. Para que cuando lleguemos a esta llamada esperada aquí, en realidad podamos continuar con la ejecución de otra co-rutina. Y veremos cómo hacerlo en el siguiente apartado. Hay una cosa más que quería mostrarte de antemano sin embargo, cuál es cómo podemos devolver valores de esto? Entonces va a ser igual que tenemos funciones regulares. Entonces vamos a renombrar esto de imprimir hola para devolverla sola. Y esto se va a volver hola en su lugar. Y así para sacar el resultado, igual que con una función regular, llamamos hola a nuestro regreso. Pero ahora porque es una función asíncrona, tenemos que esperarla. Y una vez que se hace esta función, entonces obtenemos el valor de retorno aquí. Y entonces podemos imprimirlo esto. Entonces va a hacer exactamente lo mismo. Es justo aquí. No lo estamos imprimiendo internamente, sino en lugar de devolver un valor de la función como esta, y notarás que realmente la principal diferencia para una función regular es la asíncrona y esperar. Entonces podríamos hacer lo mismo aquí, así. Y esto sería sólo una llamada de función regular. Y podemos obtener el valor devuelto desde aquí como lo haríamos normalmente. Pero esto no podemos hacer, sólo podemos esperar co rutinas. Entonces esto nos va a causar un error, como veremos en un segundo. Y algo más que tampoco podemos hacer es que no podemos. Si eliminamos esto y eliminamos esto un peso, podemos usar una palabra clave await dentro de un non y no dentro de una co-rutina. Por lo que tenemos que tener esta definición asíncrona delante para poder esperar internamente. Por lo que no podemos usar await sin tener un def asíncrono fuera de él. Y si tenemos una definición de def asíncrona asíncrona, tenemos que esperar la respuesta porque de lo contrario, básicamente estás creando un objeto de co-rutina aquí, pero nunca ha sido programado, nunca ha estado lejos, por lo que nunca se ha ejecutado en realidad, nunca se ha agregado al bucle de eventos. Entonces solo ten en cuenta estas cosas que si estás usando asíncrono, siempre tienes que esperar esta respuesta. Y la llamada de espera aquí no está bloqueando. No obstante, detendrá una mayor ejecución de la función y le devolverá el control al bucle de eventos para que otros equipos puedan correr mientras tanto. Entonces con eso, sé que es un poco confuso. La primera vez que estamos hablando a través de todo esto y hay algunos términos extraños apareciendo. Pero a medida que pasaremos por el próximo par de conferencias, ojalá consigas una comprensión más clara de cómo funciona todo esto. Y probablemente también con el tiempo, esto se volverá un poco más cómodo para ti. 23. Tareas asíncronas: Entonces lo siguiente que vamos a ver ahora es cómo podemos crear tareas que son, bueno, ya veremos. Entonces lo primero que notamos la última vez es aunque estamos usando funciones asíncronas aquí, y también podemos volver a cambiar esto a def asíncrona y tal vez simplemente devolver esto a una declaración print hello. Al igual que esto. Acabamos de imprimir hola y tunelización. A pesar de que estamos usando esta sintaxis asíncrona, la ejecución que estamos recibiendo sigue siendo esencialmente sincrónica porque no hay nada más a lo que, ya sabes, el control pueda pasar. Entonces aunque estamos usando esta sintaxis asíncrona y nuestro control se está devolviendo al bucle de eventos. No hay nada más arriba horario que pueda seguir. Y así no hay nada más en lo que se pueda trabajar mientras esperamos una respuesta. Entonces de igual manera, si tuviéramos otra llamada de sueño aquí, bueno, nota que todavía, seguimos recibiendo esta ejecución sincrónica de reciclaje va a empezar a dormir, dormirá por cinco segundos. Y luego vamos a entrar en el siguiente punto. Y aquí estamos para dormir. Aquí vamos a esperar la respuesta. Y luego aunque se devolvió la ejecución, No hay nada más que pueda continuar. Y en este punto, aunque la ejecución se devuelve al bucle de eventos, de nuevo, no hay nada que se pueda continuar porque lo único que no puede continuar más la ejecución de este bloque de funciones, porque estamos aún en espera de esta respuesta aquí. Y no hay nada más en lo que se programe así se pueda trabajar. Entonces generalmente lo que podemos tener sin embargo, es que en realidad podemos empezar a crear tareas. Por lo que podemos tener varias tareas en nuestro bucle de eventos en las que se pueden trabajar mientras se esperan las cosas. Entonces veamos un ejemplo de esto. Vamos a crear una tarea. Y vamos a hacer esto entrando en un panel de fregadero. Y vamos a llamar aquí crear tarea. Y voy a tomar esta segunda llamada de sueño asíncrona. Y voy a añadir la tarea y aquí. Y luego voy a esperar la tarea más tarde. Entonces lo que sucede cuando creamos una tarea es que básicamente programamos esta co-rutina para que se trabaje siempre que sea conveniente. Pero hasta que lo esperemos, no hay parada en el flujo de nuestra co-rutina para parar en ese punto. Entonces lo que obtenemos en este punto es recordar antes de tener nuestros dos duermes que están sucediendo uno tras otro. En este caso, hemos agregado otra tarea. Y así si en realidad volvemos a ejecutar esto, ya veremos que tenemos dos antes de dormir que están pasando. Y luego, oops, tengo un error de sintaxis aquí. Tengo que quitar la llamada de función porque es un objeto que estamos esperando, no una función o un método de coworking, porque ya tipo de llamada a la función. Entonces sólo tenemos un entrenador, un objeto que nos va a volver. Pero de todos modos, seguimos esperando esto. Pero notaremos aquí que ahora estamos durmiendo una vez y ahora estamos durmiendo otra vez. Y luego básicamente estamos empezando esto dos veces y luego estamos en el periodo de tiempo de espera, y luego estamos después de nuestro sueño. Entonces si importamos el módulo de tiempo, mientras que antes estábamos ejecutando, sigue siendo secuencialmente. Entonces podemos tener una hora de inicio aquí, que va a ser nuestro tiempo.Deltatime. Podemos imprimir aquí. El tiempo total va a ser tiempo, tiempo menos inicio. Entonces notaremos que nuestra ejecución ahora no va a ser alrededor de la marca de 10 segundos, que es lo que teníamos cuando dormíamos dos veces seguidas, sino que más bien están en la marca de 5 segundos. Por lo que hemos creado esta tarea extra. Entonces cuando entramos en la llamada de espera, ahora tenemos otra co-rutina que podemos pasar a donde otra tarea que también se puede ejecutar. Y así en este caso, en realidad estamos teniendo dos cosas que se ejecutan al mismo tiempo donde estoy, donde se puede devolver el control al bucle de eventos. Y las cosas están programadas para que se ejecuten asincrónicamente, pero esencialmente simultáneamente. Entonces si agregamos solo algún número extra aquí y que podamos imprimir para entender, ya sabes, dónde estamos en cada uno. Imprimimos n aquí, e imprimimos n aquí, y luego aquí queremos agregar uno. Esta va a ser la tarea que creemos y programemos. Y entonces aquí podemos sumar dos. Entonces si nos quedamos con esto, podemos ver que, bueno, primero, estamos reprogramando esta tarea, pero luego estamos esperando esta llamada aquí, que luego llega a esto. Y aquí es una especie de donde se detiene nuestra ejecución aquí porque sólo estamos esperando la respuesta aquí. Por lo que hemos devuelto el control al bucle de eventos. Y ahora tenemos otra tarea que se ha programado. Y ahora como un momento conveniente para trabajar en ello porque no se está trabajando en nada más. Y así esta tarea ahora es básicamente como podemos ver aquí, empezando a ejecutarse una vez que lleguemos a este punto de espera aquí. Y luego terminamos, o después termina nuestro primer Coubertin aquí. Podemos ver que la ejecución vuelve a esa co-rutina después de entrar en este paso aquí. Y entonces esperamos aquí el resultado de esta tarea. Y así ahora básicamente ya no estamos ejecutando este bloque de co-rutina hasta obtener la respuesta aquí, razón por la cual tenemos esta llamada aquí. Y luego después calificamos la respuesta de esto, razón por la cual tenemos el hola aquí. Si volteamos el orden de ejecución aquí, notarás que el orden que tenemos imprimiendo allá afuera también hay cambio tendrá el hola segundo último, y luego tendremos el after sleep después de eso por el orden de las declaraciones de espera aquí. Entonces podemos ver ahora nos estamos metiendo en esta naturaleza más concurrente porque ahora en realidad tenemos múltiples rutinas co diferentes que se están ejecutando al mismo tiempo. En este caso, solo es demasiado. Pero como saben, una co-rutina es algo así en el lugar de sólo esperar un resultado y le devuelve el control al bucle de eventos. En realidad puede seguir y puedes empezar a trabajar en otras tareas hasta que estén llega a este punto de espera. Y luego una vez terminada otra co-rutina, devolverá la ejecución o control de la ejecución a esa co-rutina. 24. Método de reforma: async: Muy bien, así que ahora hemos visto nuestro primer ejemplo de cómo tenemos esta ejecución concurrente al tener tareas programadas. Y mientras una co-rutina básicamente está esperando una respuesta, la ejecución de otra puede continuar, que es lo que teníamos cuando programamos una tarea aquí. Y luego la ejecución de una especie de sucedió cuando era conveniente, cuando no se estaba trabajando en nada más. Pero todavía tenemos este problema aquí donde por ejemplo, tenemos esta declaración print hello. Y éste todavía se espera después de esto, sólo después de que termine este sueño aquí. Y saber idealmente, no quisiéramos que idealmente estos dos pudieran correr en realidad concurrentemente a. Entonces, por ejemplo, digamos que aquí teníamos dos llamadas API que simplemente no dependían en absoluto el uno del otro. Entonces esto de aquí le pega a API uno y esto aquí le da API a Nosotros de cualquier manera, aunque lo tuviéramos así, o si lo teníamos de la manera antes, todavía no está funcionando de la manera que queríamos porque básicamente estamos esperando la respuesta de una llamada API. Y luego vamos a entonces, entonces sólo vamos a estar iniciando la convocatoria de la segunda, que no es lo que queremos. Nosotros los queremos básicamente tanto el inicio casi de inmediato, uno tras otro, y luego queremos que ese periodo de tiempo de espera se superponga para que todo ese tiempo de espera de red básicamente no esté sucediendo secuencialmente, pero casi está sucediendo en al mismo tiempo. Entonces de cualquier manera, independientemente de cómo volteemos este orden, realmente no vamos a llegar a eso. Entonces, ¿cómo podemos hacer algo así? Bueno, podemos usar es algo más de IO asíncrono, que se llama reunir. Entonces podemos entrar en IO asincrónico y aquí podemos usar este y método de recolección. Y aquí ya podemos poner una serie de corutinas y básicamente todas serán programadas y ejecutadas de forma concurrente. Entonces no tenemos éste tras otro, pero todos están programados al mismo tiempo. Y cualquiera que sea, ya sabes, lo que acabe y qué orden. Básicamente, podemos saltarnos a través de eso. Todavía hay algún orden que tenemos aquí dentro, que es el orden en el que los ponemos. Pero ahora somos capaces de ejecutar todo esto de forma concurrente y de la manera que queríamos. Entonces veamos esto en acción. ¿ Cómo haríamos esto? Bueno, podemos tener, por ejemplo, son primera co-rutina aquí, que va a ser nuestra asíncrona. Vamos a tener nuestra segunda co-rutina, que es el sueño de computadora Eysenck 2. Y luego vamos a tener nuestra tercera, que va a estar imprimiendo de hola. Ahora podemos eliminar la programación de esta tarea. Y si ejecutamos esto ahora, notaremos que vamos a entrar al de antes de dormir, que está aquí. Entonces vamos a entrar en el antes de dormir también, que está aquí. Entonces tenemos nuestra impresión baja porque ambas rutinas co lo son, no están bloqueando pero esencialmente están esperando una respuesta. Y para que puedan devolver el control a nuestro bucle de eventos. Entonces vamos aquí, ejecutamos esto, le damos ese control al bucle de eventos. Ejecutamos, vamos y aquí ejecutamos, llegamos a aquí, recuperamos el control. Entramos, aquí hay acabados de co-rutina porque no hay espera nunca. Y luego podemos volver al bucle de eventos y al peso del bucle de eventos. Y luego verá porque éste fue programado primero y duermen por el mismo tiempo. Nosotros venimos a aquí primero. Y así podemos continuar con la ejecución de esto hasta que, bueno, nuestra co-rutina termine aquí. Y luego el control da, devuelto al bucle de eventos y luego vemos qué más está pasando. Entonces tenemos éste aquí, que luego termina. Entonces actualicemos un poco esto y también solo dormamos por esa cantidad de tiempo. Veremos que la orden de programación es una especie de lo que la tenemos aquí, pero la orden de acabado puede que en realidad no sea así. Entonces en este caso, vamos a esperar que éste sea programado primero. Entonces recuperaremos el control. Una vez que lleguemos a este punto, entonces podremos empezar a correr. Este de aquí. Daría de vuelta el control. Nos acercamos a este punto, podemos correr este. Terminamos toda la co-rutina, y ahora volvemos a nuestro bucle de eventos. Y en este punto, éste en realidad terminará primero de antemano porque está durmiendo por un más lento, por un periodo menos de tiempo. Para que podamos volver a este. Termino esta co-rutina porque no pasa nada más después del sueño, después de esta declaración impresa. Y luego después tenemos la única corutina que quedaba esperando, que va a ser ésta de aquí. Entonces si ejecutamos esto, podemos ver que el orden en el que terminan puntos, básicamente podemos seguir adelante con la ejecución de esos. Y así con esto ahora tenemos una naturaleza concurrente mucho mejor porque somos capaces de, lugar de tener todas estas declaraciones p secuenciales, en cambio las tenemos todo tipo de funcionando de forma concurrente y las estamos empezando. Y cada vez que golpeamos esto aguardamos 0.1 co-rutina, básicamente podemos devolver el control y otra co-rutina puede seguir funcionando. Y si hemos dado por Control T, poco t, Entonces bucle y todo es especie de corriendo. En cuanto termine una cosa, podemos ir allá y podemos continuar con la ejecución de ese Coubertin consiguiendo esta naturaleza concurrente mucho más agradable que en realidad estamos buscando. Entonces, en este punto tal vez te estés preguntando, bueno, ¿cuál es la diferencia entre asíncrono y subproceso? Entonces en general, y si recuerdas de lo que hablamos al principio, nuestro asíncrono aquí, esto se está ejecutando en un núcleo y también en cualquier hilo único y todo se hace a través estos bucles de eventos programados donde tenemos una manera de toros y básicamente futuros que representan que va a venir una respuesta. Pero aún no está ahí. tanto que con el subproceso, estamos creando en realidad múltiples hilos diferentes y también hay sobrecarga asociada con eso. tanto que aquí estamos sólo en un solo hilo y en realidad tenemos menos sobrecarga. Ahora, generalmente, ¿cuándo usarías alguno de estos dos? Bueno, tú o yo utilizaría generalmente el subproceso cuando estamos construyendo trabajador como programas como lo hemos hecho en nuestro módulo de subprocesos, donde teníamos muchos trabajadores diferentes realizando diferentes objetivos. tanto que si solo tienes tareas individuales, como nosotros tenemos más en estos casos, entonces puedes ir a una síncrona. Obviamente, si te sientes mucho más cómodo con una u otra, probablemente tenderás a ir hacia estas cosas y probablemente puedas ver lograr concurrencia similar. Aunque solo recuerda que con Asynchronc solo estás haciendo un solo núcleo, un solo hilo, mientras que con el subproceso estás haciendo hilos múltiples de un solo núcleo. Entonces ahí está esa diferencia y también hay sobrecarga asociada con el subproceso. Pero obviamente, ya sabes, también se reduce a confortar un poco. El otro es que en aplicaciones web, muchas veces vas a estar usando asincrónico. Y así es muy habitual tener definiciones asíncronas y puntuales donde luego puedas ocultar endpoint y eso se pone más caliente al bucle de eventos para que conozcas tus diferentes endpoints y tu servidor en general es no bloqueando la ejecución porque está tratando de ejecutar cosas en paralelo. Tan asíncrono es un tipo de resumirlo. Generalmente, desde mi perspectiva, utilizó mucho para tareas así como para el desarrollo web. tanto que el subproceso, utilizaría mucho más para el trabajador de la construcción como programas como lo hemos hecho de nuevo en nuestro módulo de torneado más grande. 25. Uso de tiempo de Async: Ahora, generalmente cuando estamos tratando con la comunicación de red o algún tipo de Io, puede haber problemas en otro lugar que pueden causar algún tipo de interrupción o básicamente algunas cosas pueden tardar mucho más. Por ejemplo, si un servidor está sobrecargado o actualmente no responde o muy lento, si estamos intentando hacer ping a ese servidor y nos lleva una eternidad obtener una respuesta. Entonces aunque estemos usando algún tipo de ejecución concurrente como la que tenemos aquí, puede haber un rezagado que básicamente lo tome todo y simplemente ralentice todo porque estamos esperando que esa cosa termine. Entonces hay un buen método que podemos usar para esto. Tener algún tipo de límites sobre cuánto tiempo queremos esperar las respuestas. Y generalmente sabemos qué tan rápidos responden los endpoints, así como el rango de variabilidad que tenemos. Y sabemos que con muy alta certeza, somos capaces de obtener respuestas y menos que este periodo de tiempo. Y el periodo de tiempo es un buen momento aquí para usar. También podemos usar algo llamado el tiempo de espera. Entonces podemos hacer, por ejemplo, es podemos decir asincrónico IO punto esperar. Y esto básicamente significará que vamos a esperar estos tantos segundos. Y si nuestra co-rutina no termina en ese momento, entonces vamos a plantear una excepción de tiempo de espera para ello. Entonces digamos que le queremos dar cinco segundos. Y también vamos a envolver esto en una declaración try and except donde vamos a captar específicamente un tiempo de espera Aram. Y aquí vamos a imprimir error de tiempo de espera encontrado. Entonces en este caso, si ejecutamos esto, todo va a estar bien porque lleva dos segundos y sin límite de tiempo, son cinco segundos. Pero si cambiamos esto a, digamos treinta segundos, como si algo estuviera funcionando realmente lento o solo hay una ventana de tiempo de espera de 30 segundos y no responde. Y estamos un poco manteniendo esta conexión ahí y estamos esperando una respuesta, pero nunca va a responder. Y la conexión sólo se interrumpirá después, digamos, 30 segundos. Si ponemos aquí una espera de cinco segundos, entonces después de que lleguemos a esa marca de 5 segundos, entonces básicamente vamos a matar esto. Y en cambio vamos a llegar a un error, que podemos ver aquí en un segundo. Por lo que podemos ver que hemos encontrado un error de tiempo de espera. Y debido a que tenemos este componente de tiempo de espera aquí, ahora, ten en cuenta que porque estamos especie de encontrarnos con este caso de excepción, podemos ver que estamos entrando en el antes duerme aquí. Y en realidad hemos entrado en este caso de excepción. Entonces las otras rutinas co que también tenemos, como podemos ver aquí, que en realidad no tienen la oportunidad de terminar porque nos hemos encontrado con esta excepción con el peso por método. Entonces obviamente esto puede ser algo muy bonito de usar para asegurarte de que las partes de tu ejecución o no estén bloqueadas por mucho tiempo por razones externas. Pero obviamente también se quiere tener cuidado con esto ya que también puede interrumpir otras cosas que se están ejecutando si se les está esperando al mismo tiempo, como en este caso que tenemos aquí. 26. Crea asíncronos para los bucles: Ahora otro caso que quería repasar era asíncrono para bucles ya que a veces puede ver esto. Pero quiero repasarlo y básicamente mirar el comportamiento para asegurarnos de que entendemos qué es exactamente un bucle FOR asíncrono y qué hace y no hace. Entonces sigamos adelante y cambiemos nuestro sueño asíncrono aquí en vez de ser un generador, cual sólo va a ceder valores, y luego después se va a dormir. Entonces vamos a decir para mí en rango, y vamos a dar el resultado I. Y entonces vamos a dormir por i segundos. Y digamos para I entre uno y n. Y diremos que n es igual al valor máximo entre dos extremos. Y sólo para que hagamos algo, ¿verdad? Y así ahora lo que podemos hacer es usar un asíncrono for loop y diremos por k en un sueño de fregadero 5, y luego podemos imprimir k Está bien, así que sigamos adelante y ejecutemos esto y también hablemos a través de lo que está pasando. Entonces hemos tenido nuestros cinco años como insumo sólo porque, bueno, eso es un poco de sobreimpresión aquí todavía. Y entonces básicamente la estamos seleccionando y asegurándonos de que sean al menos dos. Y vamos a entrar en nuestro for-loop aquí, y estamos empezando de uno a n. Así que va a ser de uno hasta pero sin incluir cinco. Entonces de uno a cuatro, como vemos aquí. Y luego cedemos esta respuesta, y luego esperamos este sueño que tenemos aquí. Ahora podemos ver pasar por aquí, o el tiempo total de ejecución es de unos diez segundos. Entonces si tenemos uno más dos es tres, más tres es seis, más cuatro es diez. Entonces seguimos ejecutando esto secuencialmente. No estamos haciendo esto al mismo tiempo, de lo contrario, nuestro tiempo de ejecución será de cuatro segundos, ya que así es el sueño más largo que tenemos aquí, o aproximadamente unos cuatro segundos. Entonces lo importante de esta asíncrona para es que básicamente tenemos otra etapa donde somos capaces de devolver el control al bucle de eventos. Entonces en lugar de tener un for-loop donde básicamente sucede esta iteración tipo de todo, el avance asíncrono nos da otra etapa donde durante esta iteración, si estamos esperando una respuesta, podemos volver a dar el control al bucle de eventos para luego volver a nuestra corutina una vez que estemos listos para continuar con nuestro bucle. Entonces eso es solo una cosa importante tener en cuenta que si ves un piso asíncrono, si piensas en escribir un asíncrono para, no funciona. No se ejecuta de forma concurrente y se ejecuta secuencial, pero básicamente agrega otra etapa donde podemos devolver el control al bucle de eventos para que otras cosas puedan continuar con su ejecución. 27. Uso de bibliotecas Asynchronous: Entonces lo siguiente que quería echar un vistazo es usar otras bibliotecas con procesamiento asíncrono. Por lo que algunas bibliotecas soportan asíncronas y otras no. Y solo quiero seguir adelante y mirar a través de estos y básicamente mostrarte una comparación rápida de, ya sabes, cómo se vería eso. Entonces vamos a usar, y ya tengo como un poquito de boilerplate aquí básicamente con algunas URL que he recogido. Lo que vamos a hacer es ejecutar un programa muy sencillo, fue solo hacer pings a cada una de estas URL y luego solo obtiene la respuesta de los textos de ella. En realidad ni siquiera hace nada con él, sólo algo así como conseguirlo. Entonces vamos a escribir esto de dos maneras. Uno de ellos va a estar usando la versión sincrónica solo iba a usar la biblioteca de peticiones. Entonces no tienes eso. Puedes seguir adelante y escribir solicitudes de instalación de pip como esta. Y luego también vamos a usar el HTTP IO, que va a ser HTTP como este pip instalar eso. Y uno de estos, probablemente puedas adivinar que va a ser el HTTP nos va a permitir hacerlo de forma asíncrona mientras que el otro es biblioteca asíncrona. Entonces vamos a empezar con el sincrónico. Vamos a importar solicitudes. Y lo que vamos a hacer es que sólo vamos a correr un poco de for-loop. Vamos a decir para URL. En las URL, vamos a llamar a solicitudes dot get URL. Y entonces podemos cronometrar nuestro proceso aquí y podemos decir nuestro, nuestros tiempos de inicio tiempo.Deltatime y nuestro tiempo de fin va a ser tiempo.Deltatime. Y entonces podemos decir que las crestas tomaron y luego tenemos nuestro tiempo de fin menos inicio. Entonces solo podemos ejecutar esto y esta sólo va a ser la forma síncrona típica estándar. Y podemos ver que esto va a tomar un par de segundos, probablemente, digamos 3.5 segundos ahora mismo. Entonces sigamos adelante y escribamos la versión asíncrona de la misma. Y también veamos los componentes individuales y la calvicie. Entonces vamos a hacer estamos enfrentando a la muerte y vamos a decir obtener respuesta URL. Vamos a pasar aquí una URL. Y ahora vamos a utilizar nuestra biblioteca HTTP AIO que acabamos de importar o que acabamos de instalar. Entonces vamos a importar el HTTP IO así. Y vamos a decir con AIO http dot client session. Como sesión, vamos a hacer de esto un ancho asíncrono. Y hablaré de esto en un segundo. Y vamos a hacer asincronización con sesión, no obtengas URL como respuesta. Y luego finalmente, vamos a devolver un punto de respuesta de peso txt. Por lo que repasaremos cada una de estas líneas en la segunda. Y aquí por supuesto, también queremos asegurarnos de que obtengamos la respuesta de los textos. Entonces podemos decir que la respuesta de texto de sincronización va a ser esto. Y aquí podemos simplemente anexar a nuestra lista. Y entonces podemos hacer algo parecido. Pero aquí tenemos nuestras tareas. Y para cada uno de estos, quieres asíncrono o, queríamos crear una nueva tarea, que va a llamar a nuestra respuesta GET URL. Vamos a pasar. Eso no es lo que quiero. Muévete en absoluto. ¿ Dónde estamos? ¿Aquí? Vamos a llamarla, a través de nuestra respuesta. Vamos a proporcionar nuestra URL como entrada aquí. Y luego vamos a esperar Async IO dot se reúnen. Y vamos a dar click en todas nuestras tareas y básicamente desempaquetar toda esta lista para proporcionarlas como argumentos individuales. Y entonces nuestra respuesta de texto asíncrona va a ser la salida que obtengamos de esto. Y entonces aquí podemos decir que las solicitudes asíncronas tomaron esto. Ahora solo sigamos adelante y ejecutemos esto. Y entonces sigamos adelante y volvamos a este método aquí. Estamos de vuelta a esta co-rutina más bien para entender qué es exactamente lo que está pasando. Entonces, solo ejecutemos esto para que realmente podamos comparar el rendimiento. Por lo que tenemos nuestro proceso sincrónico en marcha. Ah, me olvidé de inicializar aquí nuestro objeto. Entonces sigamos adelante y corremos eso una vez más. Ahí vamos. Entonces con nuestro proceso sincrónico, nos llevó un poco más de tres segundos, y con nuestro proceso asíncrono, nos llevó alrededor de 1 segundo. Entonces sigamos adelante y echemos un vistazo a esto aquí. Entonces qué está pasando ya que tenemos varios ritmos diferentes, así que si has programado un poco en Python, probablemente estés familiarizado con el, con enunciado, que es básicamente estamos creando algo como contexto o razonamiento o Context Manager, que básicamente maneja la creación así como el desgarro de lo que tengamos y no tenemos que preocuparnos por cerrar algo. Pudimos usarlo dentro de este contexto de esto con declaración aquí. Ahora la asíncrona con eso vemos aquí dos veces. Cada una de estas veces básicamente estamos dando la oportunidad para el bucle de eventos. Dos, básicamente estamos devolviendo el control al bucle de eventos y estamos dando oportunidad de comenzar o continuar con otras tareas. Entonces básicamente aquí tenemos tres instancias, una con el peso y las otras dos con nuestros gestores de contextos asíncronos aquí, donde estamos devolviendo el control al bucle de eventos para que potencialmente pueda continuar con otra cosa. Por lo que hay mucho de reenviar el control al bucle de eventos que está pasando aquí. Eso realmente lo hace realmente agradable y como asíncrono, y sobre todo con estas diferentes partes. Por lo que uno de ellos en realidad sería conseguir una sesión de nuestro pool de sesiones. Entonces el siguiente sería realmente realizar las solicitudes, lo que implicaría mucha de la red esperando. Y entonces el otro componente realmente sacaría la respuesta HTML completa, porque puede que no siempre tengamos eso. Y así tenemos que reunir todos esos datos y básicamente analizarlos en una variable. Y también hay algo de tiempo de espera involucrado aquí. Entonces para cada uno de estos componentes donde en realidad podemos estar teniendo algún tipo de componente de espera. Básicamente le devolvemos el control al bucle de eventos hasta que estemos listos para continuar con esto. Por lo que hay mucho asíncrono o hay mucho de devolver el control al bucle de eventos. Estas diferentes llamadas que estamos haciendo aquí, básicamente lo estamos haciendo tres veces. En tanto que para nuestras peticiones, obviamente, la propia biblioteca solicita. ¿ Dónde estamos? Aquí vamos. Entonces esto en sí es sólo un poco de llamada de bloqueo. Y no hay, no hay conseguir asíncrono de una sesión desde una piscina. También actualmente no estamos usando sesiones en realidad en este caso. No estamos asincrónicamente, ya sabes, recibiendo la solicitud como estaríamos en este caso. Y tampoco estamos asincrónicamente tipo de conseguir esos datos HTML y tenerlos reunidos en segundo plano y luego continuar y estamos listos para ello. Ahora por supuesto, podemos optimizar un poco esto y podemos poner este auto en como un def asíncrono, obtener URLs con solicitudes, y pondremos la URL aquí. Y entonces aquí lo podemos hacer aquí, sólo podemos devolver esto. Pero como probablemente también te darás cuenta en un segundo, si tenemos nuestras tareas aquí y programamos estas tareas. Entonces entraremos a un fregadero, io punto crear tareas y probaremos fuera de bolígrafos. Y si queremos crear esto como una tarea, pasando el parámetro URL, todavía no hay llamada de espera en ninguna parte. Entonces aunque tratemos de usar este método asíncrono de asíncrono, sé que Don se reúnen, y sólo tratamos de ejecutar todas estas tareas de forma asíncrona. Y en algún lugar aquí deberíamos tener nuestra respuesta de texto hundido, creo que se llamaba. Por lo que aunque tratáramos de usar este enfoque, en realidad no vamos a obtener ningún beneficio de rendimiento de él porque no hay llamada de espera en ningún lugar. No hay ningún punto en el que regresemos el control al bucle de eventos. Entonces aunque tratemos de envolver esto en como una función asíncrona, como podemos ver aquí. Todo esto es un proceso sincrónico y está completamente bloqueando. En tanto que en nuestro proceso asíncrono, básicamente estamos teniendo estas diferentes oportunidades y obteniendo la sesión del pool, la realización real de la solicitud, así como el análisis de la respuesta de los textos para obtener un texto respuesta fuera. Cada uno de estos tres componentes básicamente nos permite devolver el control al bucle de eventos que otras cosas puedan suceder de forma concurrente o mientras esta cosa está esperando en su lugar. En tanto que en nuestro caso sincrónico, no tenemos oportunidad de hacer eso y básicamente estamos bloqueados hasta que esta solicitud la envíe, obtenga la respuesta, analize la respuesta de los textos. Entonces todo eso es un proceso de bloqueo. Entonces como podemos ver, hay algunos grandes beneficios que en realidad podemos obtener al usar solicitudes asíncronas obviamente. Pero hay que tener cuidado de que también estamos usando la biblioteca asíncrona apropiada. Entonces en este caso, va a ser un HTTP 0 para entrada y salida de archivos. También hay en realidad algo llamado archivo AI, que puedes usar donde puedes hacer que la lectura y escritura de archivos, así como solo operaciones generales de archivos algo asíncronas como esta. También hay otras cosas como conexiones a bases de datos. Hay muchas bibliotecas asíncronas que puedes reutilizar para eso. Pero tienes que asegurarte de que si intentas hacer esto asíncrono, tienes que usar las bibliotecas apropiadas también que soporten esta manera asíncrona. De lo contrario, solo vas a tener componentes de bloqueo porque es un proceso sincrónico y no hay control que se le devuelva al bucle de eventos. 28. La declaración de espera Async: Muy bien, así que hemos visto algunas cosas bastante geniales en este momento con procesos asíncronos. Pero sigamos adelante y veamos una cosa más cool, que va a estar esperando hasta que se completen algunas coordenadas o se completen algunas tareas y luego lidiemos con esas y tipo de ir sobre eso iterativamente. Porque actualmente lo que hemos visto con juntar es que básicamente estamos esperando que todo se complete. Lo que significa que si tenemos un montón de cosas que solo tardan poco tiempo y una de ellas eso es un rezagado. Esto obviamente también puede ralentizar nuestro programa. Por lo que voy a volver a importar IO asíncrono. Voy a tener mi nombre si es igual a main. Y aquí sólo voy a punto IO asincrónico, correr nuestra principal co-rutina, y vamos a seguir adelante y encontrarlo. Yo escribiré. Y también voy a volver a usar el sueño. Entonces vamos a entrar en def asíncrona y vamos a llamar a esto nuestro sueño asíncrono de nuevo. Y aquí vamos a tener un perímetro. Yo sólo cuánto tiempo vamos a dormir. O si queremos, podemos verlo un poco más explícito sobre ellos y llamarlo algo así como una duración. Y luego diremos que vamos a esperar Async IO dot sleep durante el tiempo. Y entonces sólo vamos a devolver la duración. Apenas tomó, también tienen algo devuelto de ahí. Muy bien, entonces en nuestra Coroutine principal aquí, básicamente lo que quiero hacer es agendar 10 tareas. Y luego cuando uno de ellos se completa, quiero poder lidiar con ellos. Entonces lo que voy a hacer es que voy a tener una variable aquí llamada pendiente. Y verás por qué en un segundo, que voy a inicializar para que solo sea un conjunto vacío. Entonces voy a iterar para I en el rango uno al 11. Y para cada uno de estos, voy a añadir un elemento. Y vamos a decir asíncrono IO punto crear tarea. Entonces vamos a crear nuestro sueño asíncrono con la duración específica. Entonces en este momento y ya hemos visto antes la tarea de crear. Solo estamos creando un montón de tareas que estamos agregando a este conjunto aquí que hemos llamado pendientes. ¿ De acuerdo? Entonces ahora podemos usar algo llamado Async, IO dot wait. Y aquí podemos proporcionar un intervalo de tareas. Entonces por ejemplo, un conjunto o una lista de tareas. Y, y podemos tener un comportamiento diferente para eso, que es lo que veremos en un segundo. Así que vamos a mantenerlo un poco con el comportamiento predeterminado por ahora. Entonces vamos a tener nuestro primer justo intervalo de tareas, que sólo va a ser el pendiente que tenemos aquí. Y el retorno que realmente obtenemos de ella. A las variables se les llama hecho así como pendientes. Entonces por eso tenemos este nombre de variable aquí. Porque las respuestas que obtenemos en realidad se dividen en dos cosas. Por lo que estas son las tareas que han concluido y las amarillas, las tareas que aún están pendientes. Entonces dejaremos esto así por ahora. Y luego sólo vamos a imprimir se hacen las tareas. Y también imprimiremos nuestras tareas pendientes. Y dejando eso como está por ahora y le haremos algunos cambios más en un segundo. Vamos a seguir adelante y correr eso primero. Y sí, solo sigue adelante y presiona Enter. Por lo que debería tomar unos 10 segundos. Realmente no tengo ninguna impresión extra aquí, lamentablemente en este momento excepto por están hechos y pendientes al final aquí. Pero Ahí vamos. Entonces tenemos nuestro primer conjunto de resultados, que va a ser éste de aquí. Y podemos ver que tenemos un conjunto que tipo de tiene la tarea, así como también el resultado que en realidad vino con él. Y entonces finalmente también tenemos este conjunto vacío aquí, que es básicamente las tareas pendientes pendientes pendientes. Entonces tenemos algo fresco, pero esencialmente lo que tenemos en este momento es una especie de lo mismo que ya tenemos con el encuentro en esencia porque seguimos esperando que todo termine. Por lo que hay diferentes formas en las que podemos ir para hacer esto. Una de las cosas que podemos hacer es añadir algo así como un tiempo de espera. Ahora esta vez en adelante es diferente a lo que teníamos para el peso, en este caso, básicamente estamos revisando o básicamente vamos a conseguir nuestro resultado aquí para Don y Pendiente una vez que lleguemos a este límite de tiempo de espera. Pero eso no significa que nuestras tareas programadas actuales vayan a ser canceladas. Simplemente significa que vamos a obtener nuestra respuesta en ese momento. Entonces lo que podemos hacer es decir, mientras aún hay tareas pendientes. Entonces si bien la longitud de nuestro conjunto pendiente es mayor a 0, vamos a seguir adelante e imprimir esto. Entonces si ejecutamos esto, ahora, deberíamos verlo imprimir alrededor de cada dos segundos, que es lo que tenemos aquí. Obviamente hay mucho spam a nuestra salida como podemos ver, porque es muy detallado. Cada uno de estos elementos, hay mucho detalle en ello, pero podemos ver el conjunto que tenemos para anexar resultados es básicamente una especie de simplemente disminuyendo continuamente en tamaño. Y así cada dos segundos como que regresamos y vemos qué resultados ya han terminado. Entonces lo que están en se hacen. Y luego simplemente continuamos con las actuales tareas pendientes. Ahora, obviamente si quieres sacar resultados, probablemente también queremos hacer eso. Y así en realidad podemos iterar sobre se hacen las tareas. Y podemos decir para las tareas realizadas, portal diga para Don tarea y hecho si quieres obtener el resultado, solo podemos esperar, esperar ese elemento o podemos esperar esa tarea. Y de ahí podemos sacar el resultado que tenemos aquí. Entonces sigamos adelante y corremos eso una vez más. Entonces vamos a ver básicamente el orden en el que lo esperaríamos para que terminaran estas tareas. Entonces podemos ver aquí que cada dos segundos, esencialmente, estamos deteniendo esto o estamos llegando a un tiempo de espera para nuestro Coubertin aquí y estamos recibiendo las respuestas. Pero estas tareas aún se han programado y no son técnicamente y progresan como podemos ver, porque es cada dos segundos que un poco obtenemos las respuestas. Y luego podemos recorrer sobre ellos. Y si usamos esta espera, podemos obtener el resultado real así. Pero obviamente esto es, esto es bastante bonito porque ahora no tenemos que esperar a que todo termine, pero podemos tipo de procesos en trozos ya que termina. Y por supuesto, algo que también podemos hacer es agregar más cosas a la lista pendiente o al conjunto pendiente en este caso. Entonces lo que podríamos hacer, por ejemplo, es que podríamos, ya sabes, al fondo aquí solo, tenemos más tareas que añadir. Yo sólo voy a hacer una muy simple simplemente agregando una tarea que duerme una vez. Y básicamente diremos, haremos esto una vez. Agregar tarea es igual a false. Y luego diremos, si esa tarea era cierta, si agregar tarea, entonces queremos agregar la tarea y simplemente estableceremos esta variable en false. Entonces esto es infinitamente y básicamente quedarse atascado en este bucle. Pero el punto que estoy tratando de hacer con esto es que sólo podemos seguir sumando más tareas a en este caso están pendientes de set. Y así esto nos da mucha más flexibilidad porque a medida que entran las cosas, podemos seguir creando y programando estas tareas. Y podemos obtener estas respuestas cuando estén listas usando este peso de punto IO asincrónico. En este caso, estamos usando un tiempo de espera específico, pero en realidad también hay un método diferente disponible para nosotros. Y ese parámetro se llama retorno cuando. Y aquí podemos tener diferentes opciones. El default, creo, está todo completado, escrito en todos los topes. Entonces si no establecemos un tiempo de espera, entonces sólo vamos a obtener nuestra respuesta una vez que todas las tareas hayan concluido. Y eso es un poco lo que vimos en el principio cuando no proporcionamos este parámetro, que básicamente estamos esperando a que todo se complete. Por lo que veremos de uno a 10 impreso. Y luego cuando lo agreguemos, vamos a ver otro al final aquí. Y podemos ver que básicamente estamos esperando que todo termine. Esto no es una orden porque los conjuntos no están ordenados. Entonces solo estamos consiguiendo todas las tareas terminadas como las que tenemos aquí. Pero también podemos cambiar esto, pero no lo estamos si realmente no queremos usar un tiempo de espera tampoco porque tal vez tus tareas realmente van a terminar extremadamente rápido y no estamos realmente seguros de qué usar ahí, o nosotros un poco quiero hacerlo como las tareas terminan. También podemos usar la declaración return one para que se complete primero. Entonces eso significa que cada vez que algo se completa, entonces básicamente salimos de esta co-rutina aquí y podemos continuar con el resto. Entonces en este caso, vamos a ver estos números impresos uno por uno en orden. Como podemos ver aquí. Eso se debe a que cada segundo una de nuestras corutinas, es en realidad son una de nuestras tareas, en realidad está completando. Entonces podemos ver que esto en realidad también es algo realmente, realmente genial que hacer. Porque comparado con todas las demás cosas, ya sabes, podemos encontrarnos con temas ahí atrás donde básicamente, ya sabes, si una cosa tarda mucho, mucho más tiempo en correr que todo lo demás, entonces todavía vamos a estar pasando mucho tiempo esperando. Y así esta corutina de pesos que tenemos a nuestra disposición en realidad nos permite mucha más flexibilidad en ese sentido para realmente conseguir dos cosas, ya sea cuando estén listas o también dentro intervalo de tiempo específico para que podamos continuar procesando cosas que se hacen. Y también podemos agregar más tareas para que también empezaran a trabajar para conseguir realmente un programa mucho más dinámico y aún más concurrente. 29. Combinación de Async y multiprocesamiento: Muy bien, entonces ahora quiero echar un vistazo a cómo podemos combinar el multiprocesamiento y la programación asíncrona. Porque anteriormente hablábamos de que solo podemos tener un bucle de evento por hilo. Pero algo que tenemos que recordar en Python es que también tenemos esta cosa llamada bloqueo de intérprete global, que básicamente limita la concurrencia real que podemos obtener. Pero afortunadamente, cuando hacemos multiprocesamiento, en realidad tenemos una Gill por proceso. Por lo que podemos hacer mucho uso del hardware completo disponible para nosotros, así como algunas de las limitaciones de la concurrencia de Python mediante el uso del multiprocesamiento y la combinación con asincrónico. Entonces vamos a seguir adelante e importar IO asíncrono. Y también vamos a seguir adelante e importar el multiprocesamiento. Y vamos a tener son si nombre es igual a llamada principal. Pero por ahora sólo vamos a pasar de esto. Y ahora mismo lo que voy a hacer es definir una clase llamada multiprocesamiento Async. Y esto va a heredar del multiprocesamiento, no proceses. Y entonces lo que va a hacer esta clase es que va a engendrar un proceso para nosotros. Y en este proceso entonces vamos a iniciar nuestro bucle de eventos asíncrono. Entonces vamos a seguir adelante y llamar a la inicialización y simplemente inicializar la clase padre. Y también vamos a proporcionar como parámetros algunas duraciones porque lo que vamos a hacer es simplemente vamos a emular algún tipo de temporizador IO de red de larga duración o simplemente otro tiempo de IO por solo volver a usar la co-rutina de sueño. Entonces vamos a tener definida nuestra asíncrona. Y solo llamaremos a esto el sueño asíncrono. Y aquí podemos pasar en la duración. Y todo lo que vamos a hacer es que sólo vamos a esperar nuestro asíncrono IO dot sleep para esta duración. Y esto en realidad podemos hacer un método estático ya que no estamos usando ninguno de nuestros atributos de clase aquí. Entonces también necesitamos nuestro método de ejecución. Entonces esto vamos a definir sólo la forma normal. Y en nuestro método de ejecución, están aquí queremos empezar realmente a consumir nuestro bucle de eventos. Entonces vamos a seguir adelante en asíncrono IO dot run. Y ahora necesitamos proporcionar el principal punto de entrada para nuestro bucle de eventos, lo que queríamos hacer. Por lo que también necesitábamos encontrar esa co-rutina dentro de nuestra clase. Entonces vamos a entrar en def asíncrona. Y entonces sólo vamos a, Hey, tengo aquí, sólo llamaremos a esto duerme consecutivos. Y lo que vamos a hacer aquí es que vamos a tener una lista de tareas que vamos a programar primero y luego sólo vamos a esperarlas. Entonces vamos a seguir adelante y bueno, podemos tener nuestro pendiente, que va a ser nuestro set de nuevo. Y luego diremos por duración, en duraciones a nuestro pendiente. Vamos a sumar y luego vamos a crear una tarea. Por lo que crearemos una tarea usando el autof.age asíncrono, duerma durante esta duración. Entonces básicamente lo que hicimos también en la última lección, tenemos nuestro conjunto pendiente. Entonces vamos a programar un montón de tareas en base a las duraciones de entrada aquí. Y vamos a tener que todos mantengan un seguimiento de todo ahí dentro pendiente set. Y entonces vamos a decir, mientras que la duración de la patente es mayor a 0. Y entonces vamos a decir hecho y ofender igual al peso de punto IO asincrónico. Y vamos a esperar en nuestras tareas programadas. Y usemos un tiempo de espera de solo 1 segundo aquí. Y diremos cuatro, hecho tarea y hecho. Vamos a imprimir la respuesta que tenemos y la tarea que actualmente no es nada. Entonces, solo sigamos adelante aquí y solo regresemos la duración solo para que estemos regresando algo. Está bien, y entonces vamos a llamar a esto en nuestro método de entrada para la clase de multiprocesamiento. Entonces aquí vamos a ejecutar nuestro código, auto punto resbalones consecutivos. De acuerdo, entonces repasemos esto una vez más en términos de como lo que realmente estamos haciendo aquí. Estamos heredando de la clase de proceso de punto multiprocesamiento. Y eso significa que cuando iniciamos esta clase, en realidad estamos iniciando esencialmente un niño que hereda de este proceso. Por lo que podemos crear un nuevo proceso para esto que puede ejecutarse en un núcleo separado nosotros CPU separada. También le vamos a proporcionar un conjunto de duraciones. Nuevamente, esto es sólo para tener algo aquí para que alguna tarea se conecte para que se realice por nosotros. Ahora nuestro punto de entrada, y recordarás esto desde el enhebrado. No entramos en demasiados detalles para esto, para el multiprocesamiento, pero lo recordarás desde el subproceso. Es siempre que llamamos a los puntos inicio, Ahí es donde vamos a ejecutar este método de ejecución aquí. Y en nuestro método de ejecución, todo lo que estamos haciendo es proporcionar el punto de entrada para nuestro proceso asincrónico. Entonces vamos a llamar asíncrono IO dot run. Y aquí sólo vamos a tener la principal co-rutina, que va a ser esta duerme consecutiva, que aquí definimos. Y ahora esto probablemente reconocerás de la lección anterior donde solo estamos agregando en solo programar un conjunto de tareas. Y cada una de estas tareas acaba de ir a dormir durante cierto tiempo. Y luego mientras aún tenemos tareas pendientes, solo vamos a usar este método asincrónico IO no esperar. Usando nuestras tareas pendientes aquí con un tiempo de espera de 1 segundo y cada segundo que vamos a recorrer son tareas hechas y vamos a imprimir los resultados usando esta llamada de espera aquí. Entonces ahora lo cool con esto es que podemos crear un múltiples procesos. Y pueden entonces, entonces podemos dividir así el trabajo. Y en realidad podemos tener múltiples bucles de eventos ejecutándose. Uno va a estar en cada proceso. Entonces vamos a crear las duraciones iniciales, que sólo podemos inicializar para que estén vacías. Y entonces diremos para I en rango del 1 al 11, igual que hicimos para dos duraciones, vamos a anexar I. Y ahora también podemos crear dos procesos si queremos. Entonces, solo tengamos nuestra lista aquí de procesos. Y vamos a decir para mí en el rango 2, y no voy a hacer demasiado aquí. Voy a anexar a nuestro proceso y versión inicializada de nuestro ace y clase de multiprocesamiento aquí arriba. Y lo vamos a inicializar con algunas duraciones. Y esas van a ser duraciones. Y luego vamos a ir de i a, así que tienes que hacer yo veces 5, hasta yo más una vez cinco. Y así sucesivamente. De esa manera vamos a ir básicamente sólo unos incrementos de cinco. Entonces cuando yo tenga 0, vamos a pasar de 0 a cinco. Entonces van a ser los primeros cinco elementos. Y cuando yo sea uno y vamos a ir de cinco a 10. Entonces básicamente tecnología tomando los segundos cinco elementos de ahí. Y ahora tenemos nuestros dos procesos, pero aún necesitamos iniciarlos. Entonces vamos a decir para P y procesos, solo vamos a llamar p dot start al final para p y procesos, vamos a llamar P dot join. Entonces estamos esperando que esos terminen. De acuerdo, así que sigamos adelante y ejecutemos esto. Y parece que tengo un error de sintaxis aquí arriba. Entonces déjame seguir adelante y echar un vistazo a lo que está pasando aquí. Y sigamos adelante y pasemos por nuestros registros. Por lo que nuestro Coubertin nunca fue un ponderado. Entonces intentemos eso una vez más. Ahí vamos. Entonces ahora básicamente estamos corriendo en dos procesos separados. Y sí, somos capaces de hacer esto muy bien. Uno de ellos es programar un conjunto de tareas aquí quieren una programación el otro conjunto de tareas. Obviamente esto no es súper óptimo porque bueno, para uno, sólo estamos durmiendo diez segundos y tenemos mucha de la tarea más corta en un proceso y mucha de la prueba más larga establece otro. Por lo que un proceso realmente va a terminar. Por lo que también podemos imprimir aquí. Proceso terminado en procesos van a terminar antes que el otro, lo que significa que hay algún tiempo en el que una de nuestras dos CPU en este caso que estamos usando o siempre que dos núcleos que estamos usando están sentados inactivos mientras que el otro está sigue funcionando. Por lo que obviamente podemos distribuir mejor esa carga de trabajo para ojalá obtener un mejor efecto de ella. Pero aún así, está funcionando bien. Por lo que ahora somos capaces de combinar un multiprocesamiento así como asíncrono juntos y pudimos sortear algunas de las limitaciones que tendríamos con un solo hilo y solo poder ejecutar un solo bucle de eventos. Y básicamente haciendo el mayor uso de un hardware si tenemos más de un núcleo, al poder hacer uso del multiprocesamiento. Y a través de eso entonces, poder tener un bucle de eventos individual ejecutándose en cada proceso individual, lo que ojalá también nos ayude a acelerar aún más las cosas. Porque podemos meternos en estas limitaciones donde en realidad todavía pasaremos mucho tiempo esperando sólo porque, ya sabes, sean las razones que puedan haber que, ya sabes, las cosas son lentas y aún podemos, aunque tenemos co rutinas, si tenemos miles de rutinas co son de repente con tareas programadas, todavía sólo podemos apagar entre una de ellas a la vez. Entonces, si tenemos más de un bucle de eventos, estamos más de un proceso, en realidad podemos pasar más trabajo más rápido. Y cuando se hacen las tareas, podemos llegar a ellas más rápido o cuando estén terminadas, Están esperando proceso. Podemos volver a ellos más rápido para que puedan continuar su trabajo más rápido o pasar cosas en aguas abajo y se complicen realmente. También como hicimos en nuestro ejemplo de enhebrado. Pero realmente llevándolo al siguiente nivel porque ahora estamos combinando este comportamiento asincrónico en el que podemos conseguir esa concurrencia, así como el multiprocesamiento, lo que nos da concurrencia extra con cómputos extra. Y así somos capaces de lidiar tanto con los tiempos de espera de la red con el proceso asincrónico o simplemente IO general, ni siquiera tiempo de espera para ser solo tiempos de espera generales de IO. Y podemos hacer el máximo uso de nuestro hardware mediante el uso del multiprocesamiento para que podamos utilizar todos los recursos disponibles para nosotros y hacer el mejor uso de eso. Ahora una última cosa que sí quiero mencionar, que es algo que no nos hemos encontrado aquí y puede que ni siquiera sea algo con lo que alguna vez tengas que lidiar, pero solo ten en cuenta a veces que las tareas también pueden tiempo de espera. Entonces si estás programando demasiadas cosas y tienes algún parámetro de tiempo de espera ahí. Podría ser que tus tareas realmente se agoten antes de que incluso puedas llegar a ellas. Así que ten cuidado con eso si comienzas a tropezar con algunos temas extremadamente raros porque has construido este programa extremadamente complejo Eso solo está haciendo mucho trabajo, entonces eso puede ser algo que quieres cuidar es, ya sabes, Yo mi programación demasiadas tareas al mismo tiempo y o algunas de ellas en realidad el tiempo fuera antes de que pueda incluso llegar a lidiar con ellas. En cuyo caso, es posible que desee reducir los tamaños de sus lotes para que pueda pasar por esos de una mejor manera. Así que sólo una especie de último consejo que son si vas a ir realmente profundo con esto y tratar de construir algo muy grande y complejo que va a cuidar de un montón de cosas. Tan solo ten en cuenta los tamaños de tus lotes. Porque, ya sabes, eso podría ser algo puede que ni siquiera lo sea, pero podría ser algo con lo que podrías encontrarte. Y puedo causar mucho dolor de cabeza si ni siquiera estás seguro de lo que buscas. Pero sí, así que espero que hayas disfrutado de eso y espero que hayas aprendido mucho y espero que ahora puedas construir algunos programas concurrentes y paralelos realmente geniales.