0% encontró este documento útil (0 votos)
15 vistas10 páginas

Concurrencia y Paralelismo Phyton

Phyton
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como DOCX, PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
15 vistas10 páginas

Concurrencia y Paralelismo Phyton

Phyton
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como DOCX, PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 10

# Guía Completa: Concurrencia y Paralelismo en Python

## Optimiza tus Aplicaciones con Ejecución Simultánea

### Introducción

La concurrencia y el paralelismo son conceptos fundamentales para


crear aplicaciones eficientes que pueden manejar múltiples tareas
simultáneamente. Python ofrece varias herramientas para
implementar estos conceptos.

### Diferencias Clave

- **Concurrencia**: Maneja múltiples tareas progresando


simultáneamente

- **Paralelismo**: Ejecuta múltiples tareas exactamente al mismo


tiempo

- **GIL (Global Interpreter Lock)**: Limitación de Python que afecta el


paralelismo real

### Threading: Concurrencia con Hilos

#### 1. Uso Básico de Threads

```python

Import threading

Import time

Def tarea(nombre, tiempo_espera):

Print(f”Iniciando tarea {nombre}”)

Time.sleep(tiempo_espera)

Print(f”Completada tarea {nombre}”)

# Crear y ejecutar threads

Thread1 = threading.Thread(target=tarea, args=(“A”, 2))


Thread2 = threading.Thread(target=tarea, args=(“B”, 1))

Thread1.start()

Thread2.start()

Thread1.join()

Thread2.join()

```

#### 2. Sincronización con Locks

```python

Lock = threading.Lock()

Contador = 0

Def incrementar():

Global contador

With lock:

Actual = contador

Time.sleep(0.1) # Simula trabajo

Contador = actual + 1

# Uso seguro en múltiples threads

Threads = [threading.Thread(target=incrementar) for _ in range(5)]

For t in threads:

t.start()

for t in threads:

t.join()

```
### Multiprocessing: Paralelismo Real

#### 1. Procesos Básicos

```python

From multiprocessing import Process, Queue

Def procesar_datos(queue, datos):

Resultado = sum(datos)

Queue.put(resultado)

# Crear cola y procesos

If __name__ == ‘__main__’:

Queue = Queue()

Datos1 = list(range(1, 5000000))

Datos2 = list(range(5000000, 10000000))

P1 = Process(target=procesar_datos, args=(queue, datos1))

P2 = Process(target=procesar_datos, args=(queue, datos2))

P1.start()

P2.start()

Resultado1 = queue.get()

Resultado2 = queue.get()

P1.join()

P2.join()

Print(f”Resultado total: {resultado1 + resultado2}”)


```

#### 2. Pool de Procesos

```python

From multiprocessing import Pool

Def procesar_chunk(datos):

Return sum(x * x for x in datos)

If __name__ == ‘__main__’:

With Pool(processes=4) as pool:

Datos = list(range(1000000))

Chunks = [datos[i::4] for i in range(4)]

Resultados = pool.map(procesar_chunk, chunks)

Total = sum(resultados)

```

### AsyncIO: Programación Asíncrona

#### 1. Corrutinas Básicas

```python

Import asyncio

Async def tarea_asincrona(nombre, duracion):

Print(f”Iniciando {nombre}”)

Await asyncio.sleep(duracion)

Print(f”Completado {nombre}”)

Return f”Resultado de {nombre}”


Async def main():

# Ejecutar tareas concurrentemente

Resultados = await asyncio.gather(

Tarea_asincrona(“Tarea 1”, 2),

Tarea_asincrona(“Tarea 2”, 1),

Tarea_asincrona(“Tarea 3”, 3)

Print(resultados)

# Ejecutar el evento loop

Asyncio.run(main())

```

#### 2. Productores y Consumidores

```python

Async def productor(queue):

For i in range(5):

Await queue.put(f”item {i}”)

Await asyncio.sleep(1)

Await queue.put(None) # Señal de finalización

Async def consumidor(queue):

While True:

Item = await queue.get()

If item is None:

Break

Print(f”Procesando {item}”)

Await asyncio.sleep(0.5)
Async def main():

Queue = asyncio.Queue()

Await asyncio.gather(productor(queue), consumidor(queue))

```

### Patrones Avanzados

#### 1. Thread Pool Executor

```python

From concurrent.futures import ThreadPoolExecutor

Import requests

Def descargar_url(url):

Response = requests.get(url)

Return f”{url}: {len(response.content)} bytes”

Urls = [

http://example.com,

http://example.org,

http://example.net

With ThreadPoolExecutor(max_workers=3) as executor:

Resultados = list(executor.map(descargar_url, urls))

```

#### 2. Process Pool Executor

```python

From concurrent.futures import ProcessPoolExecutor


Import math

Def calcular_primos(n):

Return len([x for x in range(2, n)

If all(x % i ¡= 0 for i in range(2, int(math.sqrt(x)) + 1))])

Numeros = [100000, 200000, 300000, 400000]

With ProcessPoolExecutor(max_workers=4) as executor:

Resultados = list(executor.map(calcular_primos, numeros))

```

### Mejor Uso para Cada Caso

#### 1. Usar Threading para:

- Operaciones I/O intensivas

- Interfaces de usuario

- Operaciones de red

```python

Def descargar_archivos(urls):

Def descargar(url):

# Código de descarga aquí

Pass

Threads = []

For url in urls:

Thread = threading.Thread(target=descargar, args=(url,))

Threads.append(thread)

Thread.start()
For thread in threads:

Thread.join()

```

#### 2. Usar Multiprocessing para:

- Operaciones CPU intensivas

- Procesamiento de datos

- Cálculos complejos

```python

Def procesar_imagen(imagen):

# Procesamiento pesado aquí

Pass

If __name__ == ‘__main__’:

With ProcessPoolExecutor() as executor:

Imágenes = [‘img1.jpg’, ‘img2.jpg’, ‘img3.jpg’]

Resultados = executor.map(procesar_imagen, imágenes)

```

#### 3. Usar AsyncIO para:

- Servidores web

- Operaciones de red escalables

- Microservicios

```python

Async def servidor_web():

Async def manejar_cliente(reader, writer):

Data = await reader.read(100)

Writer.write(data)
Await writer.drain()

Writer.close()

Server = await asyncio.start_server(

Manejar_cliente, ‘127.0.0.1’, 8888)

```

### Mejores Prácticas

1. **Gestión de Recursos**

```python

# Usar context managers

With ThreadPoolExecutor() as executor:

# Código aquí

Pass

```

2. **Control de Errores**

```python

Async def manejar_errores():

Try:

Await operación_asincrona()

Except Exception as e:

Logging.error(f”Error: {e}”)

Finally:

Await limpiar_recursos()

```

3. **Monitoreo de Rendimiento**
```python

Import time

Def medir_tiempo(func):

Def wrapper(*args, **kwargs):

Inicio = time.time()

Resultado = func(*args, **kwargs)

Fin = time.time()

Print(f”Tiempo de ejecución: {fin – inicio} segundos”)

Return resultado

Return wrapper

```

### Conclusión

La elección entre concurrencia y paralelismo depende de tu caso de


uso específico. Threading es mejor para I/O, multiprocessing para
CPU, y asyncio para operaciones asíncronas. Comprende las
diferencias y elige la herramienta adecuada para cada tarea.

También podría gustarte