Fundamentos de Programación y Python

1

¿Por qué aprender Python?

2

Introducción a Python

3

Conceptos Básicos de Programación

4

Práctica: Te doy la bienvenida a los ejercicios interactivos

5

Manipulación de Cadenas de Texto en Python

6

Enteros, Flotantes y Booleanos

7

Todo lo que Debes Saber sobre print en Python

8

Operaciones Matemáticas en Python

9

Operaciones de Entrada/Salida en Consola

Colección y Procesamiento de Datos en Python

10

Listas

11

Método slice

12

Listas de más dimensiones y Tuplas

13

Aplicación de Matrices

14

Diccionarios

15

Comprehension Lists en Python (CLASE NUEVA)

Control de Flujo en Python

16

Estructuras condicionales

17

Bucles y Control de Iteraciones

18

Generadores e Iteradores

Funciones y Manejo de Excepciones en Python

19

Uso de Funciones en Python

20

Funciones Lambda y Programación Funcional en Python

21

¿Cómo realizar una función recursiva en Python?

22

Manejo de Excepciones y Uso de Pass (CLASE NUEVA)

Programación Orientada a Objetos en Python

23

Fundamentos de Programación Orientada a Objetos en Python

24

Ejercicio Biblioteca con POO

25

Herencia en POO con Python

26

Objetos heredados

27

Los 4 pilares de la programacion orientada a objetos

28

Uso de super() en Python (CLASE NUEVA)

29

Superando los Fundamentos de Programación Orientada a Objetos en Python

Lectura y escritura de archivos

30

Manejo de Archivos .TXT (CLASE NUEVA)

31

Manejo de Archivos CSV (CLASE NUEVA)

32

Manejo de Archivos JSON (CLASE NUEVA)

Biblioteca estándar de Python

33

Biblioteca estándar en Python (CLASE NUEVA)

34

Librería Os, Math y Random (CLASE NUEVA)

35

Librería Statistics y Análisis Estadístico (CLASE NUEVA)

36

Proyecto final: Guerra naval

Conceptos avanzados de Python

37

Recapitulación de lo aprendido hasta ahora

38

Escribir código Pythonico y profesional

39

Comentarios y Docstrings en Python

40

Scope y closures: variables locales y globales

41

Anotaciones de tipo

42

Validación de tipos en métodos

43

Librería Collections y Enumeraciones

Decoradores

44

Decoradores en Python

45

Decoradores anidados y con parámetros

46

Uso de Decoradores en clases y métodos

Métodos y estructura de clases en Python

47

Métodos mágicos

48

Sobrecarga de operadores

49

Implementación de `if __name__ == "__main__":`

50

Metaprogramación en Python

51

Uso de *args y **kwargs

52

Métodos privados y protegidos

53

Gestión avanzada de propiedades

54

Métodos estáticos y de clase avanzados

Programación concurrente y asíncrona

55

Introducción a la concurrencia y paralelismo

56

Threading y multiprocessing en Python

57

Asincronismo con asyncio

58

Asincronismo y concurrencia

Creación de módulos y paquetes

59

Creación de módulos en Python

60

Gestión de paquetes

61

Publicación de paquetes en PyPI

Proyecto final

62

Implementación de un sistema completo

63

Implementación de un Sistema Completo

Curso de Python

Curso de Python

Carli Code

Carli Code

Threading y multiprocessing en Python

56/63

Lectura

Uso de threading y multiprocessing en Python

DALLE_2024-10-16_17.25.15_-_A_rectangular_image_representing_threads_and_multi-processing_in_Python.The_image_should_feature_a_visual_metaphor_of_a_computers_CPU_with_multiple.jpg

Imagina que estás trabajando en una aplicación que necesita procesar múltiples tareas al mismo tiempo: desde manejar solicitudes web hasta realizar cálculos complejos de manera simultánea. A medida que las aplicaciones se vuelven más exigentes, las soluciones básicas de concurrencia ya no son suficientes. Aquí es donde entran las herramientas avanzadas de Python como threading y multiprocessing, que te permiten sacar el máximo provecho de tu CPU y gestionar tareas de manera eficiente y sin errores.

...

Regístrate o inicia sesión para leer el resto del contenido.

Aportes 5

Preguntas 0

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

me estaba costando entender el ejemplo de multi procesing pues no encontraba cual era el proceso principal y cual el secundario, si alguien mas tuvo este problema aca la explicacion que me hizo entender. En el código que has compartido, distinguimos entre el proceso principal y el proceso secundario de la siguiente manera: \### \*\*Proceso Principal\*\* El proceso principal es aquel que inicia y maneja todo el programa. En este caso, el proceso principal es el que ejecuta el bloque de código dentro de `if \_\_name\_\_ == "\_\_main\_\_":`. Es responsable de: \- Definir la lista `numeros`. \- Crear la cola `cola` para la comunicación entre procesos. \- Crear y empezar el proceso secundario. \- Esperar a que el proceso secundario termine. \- Extraer y mostrar los resultados de la cola. \### \*\*Proceso Secundario\*\* El proceso secundario es el que se crea específicamente para ejecutar una tarea en paralelo al proceso principal. En este caso, el proceso secundario se define con la línea `proceso = multiprocessing.Process(target=calcular\_cuadrado, args=(numeros, cola))` y se inicia con `proceso.start()`. Este proceso secundario: \- Ejecuta la función `calcular\_cuadrado(numeros, cola)`. \- Realiza el cálculo de los cuadrados de los números en la lista `numeros`. \- Inserta los resultados en la cola `cola`. \### \*\*Explicación de la Cola (Queue)\*\* La cola `Queue` se utiliza para permitir la comunicación entre el proceso secundario y el proceso principal. El proceso secundario coloca los resultados de los cálculos en la cola, y luego el proceso principal extrae esos resultados para mostrarlos. \### \*\*Flujo del Código\*\* 1\. \*\*Proceso Principal\*\*: Define la lista `numeros` y crea la cola `cola`. 2\. \*\*Proceso Principal\*\*: Crea el proceso secundario con la función objetivo `calcular\_cuadrado`. 3\. \*\*Proceso Principal\*\*: Inicia el proceso secundario. 4\. \*\*Proceso Secundario\*\*: Ejecuta la función `calcular\_cuadrado`, calcula los cuadrados y coloca los resultados en la cola. 5\. \*\*Proceso Principal\*\*: Espera a que el proceso secundario termine con `proceso.join()`. 6\. \*\*Proceso Principal\*\*: Extrae los resultados de la cola y los imprime. Este esquema permite que el proceso secundario haga cálculos de manera independiente, mientras que el proceso principal sigue manejando otras tareas y eventualmente recopila los resultados. by copilot
### Paralelismo con `multiprocessing` El módulo `multiprocessing` permite ejecutar múltiples procesos en diferentes núcleos de CPU, lo que es ideal para tareas CPU-bound, como cálculos intensivos. ```python import multiprocessing import time def tarea(nombre): print(f"Inicio de {nombre}") time.sleep(2) print(f"Fin de {nombre}") # Crear dos procesos proceso1 = multiprocessing.Process(target=tarea, args=("Proceso 1",)) proceso2 = multiprocessing.Process(target=tarea, args=("Proceso 2",)) # Iniciar los procesos proceso1.start() proceso2.start() # Esperar a que los procesos terminen proceso1.join() proceso2.join() print("Todas las tareas han terminado.") ```
si tambien intentaron imprimir antes del join y no les imprimio nada Antes del join: El proceso secundario aún no ha terminado, por lo que la cola podría estar vacía. Después del join: El proceso secundario ha terminado, y la cola contiene los elementos que el proceso secundario ha puesto. El método join() es crucial para sincronizar el proceso principal con el proceso secundario, asegurando que el proceso secundario haya completado su tarea antes de que el proceso principal continúe.
```js import threading import multiprocessing # Variable compartida saldo = 0 lock = threading.Lock() # Crear un Lock def depositar(dinero): global saldo for _ in range(100000): with lock: # Bloquear el acceso para evitar condiciones de carrera saldo += dinero hilos = [] for _ in range(2): hilo = threading.Thread(target=depositar, args=(1,)) hilos.append(hilo) hilo.start() for hilo in hilos: hilo.join() print(f"Saldo final: {saldo}") # Esperamos ver 200000 como saldo def calcular_cuadrado(numeros, cola): for n in numeros: cola.put(n * n) if __name__ == "__main__": numeros = [1, 2, 3, 4, 5] cola = multiprocessing.Queue() proceso = multiprocessing.Process(target=calcular_cuadrado, args=(numeros, cola)) proceso.start() proceso.join() # Extraer resultados de la cola while not cola.empty(): print(cola.get()) class CuentaBancaria: def __init__(self, saldo): self.saldo = saldo self.lock = threading.RLock() def transferir(self, otra_cuenta, cantidad): with self.lock: self.saldo -= cantidad otra_cuenta.depositar(cantidad) def depositar(self, cantidad): with self.lock: self.saldo += cantidad cuenta1 = CuentaBancaria(500) cuenta2 = CuentaBancaria(300) hilo1 = threading.Thread(target=cuenta1.transferir, args=(cuenta2, 200)) hilo2 = threading.Thread(target=cuenta2.transferir, args=(cuenta1, 100)) hilo1.start() hilo2.start() hilo1.join() hilo2.join() print(f"Saldo cuenta1: {cuenta1.saldo}") print(f"Saldo cuenta2: {cuenta2.saldo}") def agregar_valores(lista_compartida): for i in range(5): lista_compartida.append(i) if __name__ == "__main__": with multiprocessing.Manager() as manager: lista_compartida = manager.list() proceso1 = multiprocessing.Process(target=agregar_valores, args=(lista_compartida,)) proceso2 = multiprocessing.Process(target=agregar_valores, args=(lista_compartida,)) proceso1.start() proceso2.start() proceso1.join() proceso2.join() print(f"Lista compartida: {lista_compartida}") ```
En Python, las bibliotecas `threading` y `multiprocessing` permiten ejecutar múltiples tareas en paralelo, pero tienen diferencias importantes. \*\*`threading`\*\* se usa principalmente para tareas de entrada/salida (I/O), como redes o acceso a archivos, debido a la limitación del \*\*Global Interpreter Lock (GIL)\*\*. \*\*`multiprocessing`\*\*, por otro lado, permite ejecutar código en múltiples procesos y es más adecuado para tareas que consumen mucha CPU, ya que evita el GIL. A continuación, detallo cada biblioteca y su uso. \### 1. `threading`: Concurrencia a través de hilos La biblioteca `threading` permite la creación y manejo de hilos en Python. Los hilos comparten el mismo espacio de memoria y recursos, lo que facilita la comunicación entre ellos, pero limita su uso en tareas intensivas en CPU debido al GIL. \#### Uso básico de `threading` ```python import threading def tarea(nombre): print(f"Iniciando {nombre}") \# Simulación de trabajo for i in range(3): print(f"{nombre} ejecutando {i}") print(f"Terminando {nombre}") \# Crear hilos hilo1 = threading.Thread(target=tarea, args=("Hilo 1",)) hilo2 = threading.Thread(target=tarea, args=("Hilo 2",)) \# Iniciar hilos hilo1.start() hilo2.start() \# Esperar a que terminen hilo1.join() hilo2.join() ``` \#### Ventajas y Limitaciones de `threading` \- \*\*Ventajas\*\*: Ideal para tareas de entrada/salida que pueden esperar (ej., operaciones de red, archivos). \- \*\*Limitaciones\*\*: Debido al GIL, solo un hilo puede ejecutar bytecode de Python a la vez, lo que limita la utilidad de `threading` para operaciones que consumen mucha CPU. \### 2. `multiprocessing`: Paralelismo con múltiples procesos La biblioteca `multiprocessing` permite la ejecución de tareas en múltiples procesos, cada uno con su propio intérprete de Python, evitando el GIL. Esto es útil para tareas que requieren cálculos intensivos, como el procesamiento de datos. \#### Uso básico de `multiprocessing` ```python from multiprocessing import Process def tarea(nombre): print(f"Iniciando {nombre}") \# Simulación de trabajo for i in range(3): print(f"{nombre} ejecutando {i}") print(f"Terminando {nombre}") \# Crear procesos proceso1 = Process(target=tarea, args=("Proceso 1",)) proceso2 = Process(target=tarea, args=("Proceso 2",)) \# Iniciar procesos proceso1.start() proceso2.start() \# Esperar a que terminen proceso1.join() proceso2.join() ``` \#### Ventajas y Limitaciones de `multiprocessing` \- \*\*Ventajas\*\*: Permite un verdadero paralelismo, útil para tareas CPU intensivas. Cada proceso tiene su propio espacio de memoria y no está afectado por el GIL. \- \*\*Limitaciones\*\*: Cada proceso consume más memoria y tiene más sobrecarga en la comunicación entre procesos que los hilos. \### Comunicación entre Hilos y Procesos \#### `threading`: Comunicación a través de variables compartidas En `threading`, los hilos pueden compartir variables y recursos de la misma clase, ya que todos operan en el mismo espacio de memoria. Es importante utilizar \*\*bloqueos (locks)\*\* para evitar problemas de sincronización. ```python import threading contador = 0 bloqueo = threading.Lock() def incrementar(): global contador for \_ in range(1000): with bloqueo: # Bloqueo para evitar condiciones de carrera contador += 1 \# Crear hilos hilos = \[threading.Thread(target=incrementar) for \_ in range(5)] \# Iniciar hilos for hilo in hilos: hilo.start() \# Esperar a que terminen for hilo in hilos: hilo.join() print(f"Contador final: {contador}") ``` \#### `multiprocessing`: Comunicación a través de colas y pipes Dado que los procesos no comparten memoria, `multiprocessing` proporciona colas (`Queue`) y pipes (`Pipe`) para la comunicación. ```python from multiprocessing import Process, Queue def productor(q): for i in range(5): q.put(i) # Añadir elementos a la cola print(f"Producto {i} añadido a la cola") def consumidor(q): while not q.empty(): item = q.get() # Obtener elementos de la cola print(f"Producto {item} consumido") cola = Queue() \# Crear procesos p1 = Process(target=productor, args=(cola,)) p2 = Process(target=consumidor, args=(cola,)) \# Iniciar procesos p1.start() p2.start() \# Esperar a que terminen p1.join() p2.join() ``` \### Cuándo usar `threading` vs `multiprocessing` | \*\*Situación\*\* | \*\*Biblioteca recomendada\*\* | |---------------------------------------------|----------------------------| | Tareas I/O intensivas (red, lectura/escritura)| `threading` | | Tareas CPU intensivas (procesamiento de datos)| `multiprocessing` | | Necesidad de comunicación sencilla entre tareas | `threading` con variables compartidas y locks | | Necesidad de aislamiento de datos | `multiprocessing` con `Queue` o `Pipe` | \### Resumen \- \*\*`threading`\*\* es ideal para tareas concurrentes y basadas en I/O donde el GIL no es un problema. \- \*\*`multiprocessing`\*\* permite el verdadero paralelismo y es mejor para tareas intensivas en CPU. \- La \*\*comunicación\*\* entre hilos se hace mediante variables compartidas y bloqueos, mientras que en `multiprocessing` se utilizan `Queue` y `Pipe` para compartir datos entre procesos. Ambas bibliotecas son útiles para optimizar el rendimiento en Python, pero elegir la correcta depende del tipo de tarea y del diseño de la aplicación.