Ir al contenido principal

Asyncio: una introducción

Breve introducción a las E/S asíncronas con el paquete asyncio.
Actualizado 17 sept 2026  · 12 min leer

Explorar con IA

ChatGPTClaudePerplexity

El módulo asyncio se añadió a Python en la versión 3.4 como paquete provisional. Esto significa que es posible que asyncio reciba cambios incompatibles con versiones anteriores o incluso que sea eliminado en una versión futura de Python.

Según la documentación, asyncio «proporciona la infraestructura para escribir código concurrente monohilo usando corrutinas, multiplexar el acceso de E/S sobre sockets y otros recursos, ejecutar clientes y servidores de red y otras primitivas relacionadas». Este capítulo no pretende cubrir todo lo que puedes hacer con asyncio; aun así, aprenderás a usar el módulo y por qué resulta útil.

Si necesitas algo parecido a asyncio en una versión antigua de Python, quizá te interese echar un vistazo a Twisted o gevent.

Definiciones

El módulo asyncio proporciona un marco de trabajo que gira en torno al bucle de eventos. Un bucle de eventos básicamente espera a que ocurra algo y luego reacciona ante ese evento. Se encarga de gestionar, entre otras cosas, la E/S y los eventos del sistema.

De hecho, asyncio dispone de varias implementaciones de bucle. El módulo elige por defecto la más eficiente para el sistema operativo en el que se ejecuta; no obstante, puedes seleccionar explícitamente el bucle de eventos si lo prefieres. Un bucle de eventos viene a decir «cuando ocurra el evento A, reacciona con la función B».

Piensa en un servidor que espera a que alguien solicite un recurso, como una página web. Si el sitio no es muy popular, el servidor estará ocioso mucho tiempo. Pero cuando reciba una petición, tendrá que reaccionar. Esa reacción se conoce como gestión de eventos. Cuando un usuario carga la página, el servidor comprueba y llama a uno o varios gestores de eventos. Una vez que esos gestores terminan, deben devolver el control al bucle de eventos. Para hacer esto en Python, asyncio utiliza corrutinas.

Una corrutina es una función especial que puede ceder el control a quien la invoca sin perder su estado. Es consumidora y una extensión de un generador. Una de sus grandes ventajas frente a los hilos es que consumen muy poca memoria al ejecutarse. Ten en cuenta que, cuando llamas a una función corrutina, no se ejecuta realmente. En su lugar, devuelve un objeto corrutina que puedes pasar al bucle de eventos para que lo ejecute inmediatamente o más adelante.

Otro término con el que probablemente te encontrarás al usar el módulo asyncio es future. Un future es básicamente un objeto que representa el resultado de un trabajo que aún no ha terminado. Tu bucle de eventos puede vigilar objetos future y esperar a que finalicen. Cuando un future termina, pasa a estado done. Asyncio también admite bloqueos y semáforos.

La última pieza que quiero mencionar es la Task. Una Task es un contenedor para una corrutina y una subclase de Future. Incluso puedes planificar una Task usando el bucle de eventos.

async y await

Las palabras clave async y await se añadieron en Python 3.5 para definir corrutinas nativas y diferenciarlas de las corrutinas basadas en generadores. Si quieres una descripción detallada de async y await, consulta la PEP 492.

En Python 3.4, crearías una corrutina así:

eyJsYW5ndWFnZSI6InB5dGhvbiIsInNhbXBsZSI6IiMgUHl0aG9uIDMuNCBjb3JvdXRpbmUgZXhhbXBsZVxuIyBJbXBvcnQgYGFzeW5jaW9gXG5pbXBvcnQgX19fX19fX1xuIFxuQGFzeW5jaW8uY29yb3V0aW5lXG5kZWYgbXlfY29ybygpOlxuICAgIHlpZWxkIGZyb20gZnVuYygpIiwic29sdXRpb24iOiIjIFB5dGhvbiAzLjQgY29yb3V0aW5lIGV4YW1wbGVcbmltcG9ydCBhc3luY2lvXG4gXG5AYXN5bmNpby5jb3JvdXRpbmVcbmRlZiBteV9jb3JvKCk6XG4gICAgeWllbGQgZnJvbSBmdW5jKCkiLCJzY3QiOiJFeCgpLnRlc3RfaW1wb3J0KFwiYXN5bmNpb1wiKVxuRXgoKS50ZXN0X3N0dWRlbnRfdHlwZWQoXCJAYXN5bmNpby5jb3JvdXRpbmVcIiwgcGF0dGVybj1GYWxzZSxub3RfdHlwZWRfbXNnPVwiRGlkIHlvdSBhZGQgYEBhc3luY2lvLmNvcm91dGluZWAgdG8gdGhlIGNvZGU/XCIpXG5FeCgpLnRlc3RfZnVuY3Rpb25fZGVmaW5pdGlvbihcIm15X2Nvcm9cIilcbnN1Y2Nlc3NfbXNnKFwiWW91IGhhdmUgc3VjY2Vzc2Z1bGx5IGNyZWF0ZWQgYSBjb3JvdXRpbmUgaW4gUHl0aG9uIDMuNCEgQnV0IHdoYXQgYWJvdXQgbWFraW5nIHRoaXMgY29yb3V0aW5lIGluIFB5dGhvbiAzLjU/XCIpIn0=

Este decorador sigue funcionando en Python 3.5, pero el módulo types recibió una actualización en forma de una función coroutine que ahora te indica si lo que estás usando es una corrutina nativa o no. A partir de Python 3.5, puedes usar async def para definir sintácticamente una función corrutina.

Así que la función anterior quedaría así:

eyJsYW5ndWFnZSI6InB5dGhvbiIsInNhbXBsZSI6ImltcG9ydCBfX19fX19fXG4gXG5hc3luYyBkZWYgX19fX19fXygpOlxuICAgIGF3YWl0IGZ1bmMoKSIsInNvbHV0aW9uIjoiaW1wb3J0IGFzeW5jaW9cbiBcbmFzeW5jIGRlZiBteV9jb3JvKCk6XG4gICAgYXdhaXQgZnVuYygpIiwic2N0IjoiRXgoKS50ZXN0X2ltcG9ydChcImFzeW5jaW9cIilcbkV4KCkudGVzdF9zdHVkZW50X3R5cGVkKFwiYXN5bmMgZGVmIG15X2Nvcm8oKTpcIiwgcGF0dGVybj1GYWxzZSwgbm90X3R5cGVkX21zZz1cIkRpZCB5b3UgZGVmaW5lIHRoZSBhc3luYyBkZWYgZnVuY3Rpb24gYG15X2Nvcm8oKWA/XCIpXG5FeCgpLnRlc3Rfc3R1ZGVudF90eXBlZChcImF3YWl0IGZ1bmMoKVwiLCBwYXR0ZXJuPUZhbHNlLCBub3RfdHlwZWRfbXNnPVwiRGlkIHlvdSBhZGQgYGF3YWl0IGZ1bmN0KClgIHRvIHRoZSBhc3luYyBkZWYgZnVuY3Rpb24gYG15X2Nvcm8oKWA/XCIpXG5zdWNjZXNzX21zZyhcIldlbGwgZG9uZSEgWW91IGhhdmUgbm93IGNyZWF0ZWQgYSBjb3JvdXRpbmUgdXNpbmcgUHl0aG9uIDMuNSFcIikifQ==

Cuando defines una corrutina de esta forma, no puedes usar yield dentro de la función corrutina. En su lugar, debe incluir una sentencia return o await, que sirven para devolver valores al invocador. Ten presente que la palabra clave await solo puede usarse dentro de una función async def.

Las palabras clave async/await pueden considerarse una API para programar de forma asíncrona. El módulo asyncio es simplemente un framework que casualmente utiliza async/await para la programación asíncrona. De hecho, hay un proyecto llamado curio que demuestra este concepto, ya que es una implementación independiente de un bucle de eventos que usa async/await bajo el capó.

Un mal ejemplo de corrutina

Aunque viene bien tener bastante contexto sobre cómo funciona todo esto, a veces solo quieres ver ejemplos para hacerte una idea de la sintaxis y de cómo encajar las piezas.

Con eso en mente, ¡empecemos con un ejemplo sencillo!

Una tarea bastante común es descargar un archivo de algún sitio, ya sea un recurso interno o un archivo en Internet. Normalmente querrás descargar más de uno.

Así que vamos a crear un par de corrutinas para hacerlo:

import asyncio
import os
import urllib.request
 
async def download_coroutine(url):
    #"A coroutine to download the specified url"
    request = urllib.request.urlopen(url)
    filename = os.path.basename(url)
 
    with open(filename, 'wb') as file_handle:
        while True:
            chunk = request.read(1024)
            if not chunk:
                break
            file_handle.write(chunk)
    msg = 'Finished downloading {filename}'.format(filename=filename)
    return msg
 
async def main(urls):
    """
    Creates a group of coroutines and waits for them to finish
    """
    coroutines = [download_coroutine(url) for url in urls]
    completed, pending = await asyncio.wait(coroutines)
    for item in completed:
        print(item.result())
 
 
if __name__ == '__main__':
    urls = ["http://www.irs.gov/pub/irs-pdf/f1040.pdf",
            "http://www.irs.gov/pub/irs-pdf/f1040a.pdf",
            "http://www.irs.gov/pub/irs-pdf/f1040ez.pdf",
            "http://www.irs.gov/pub/irs-pdf/f1040es.pdf",
            "http://www.irs.gov/pub/irs-pdf/f1040sb.pdf"]
 
    event_loop = asyncio.get_event_loop()
    try:
        event_loop.run_until_complete(main(urls))
    finally:
        event_loop.close()

En este código importamos los módulos necesarios y luego creamos nuestra primera corrutina usando la sintaxis async. Esta corrutina se llama download_coroutine y utiliza urllib de Python para descargar la URL que se le pase. Cuando termina, devuelve un mensaje indicándolo.

La otra corrutina es la principal. Básicamente toma una lista de una o más URLs y las pone en cola. Usamos la función wait de asyncio para esperar a que las corrutinas terminen. Por supuesto, para que las corrutinas empiecen realmente, hay que añadirlas al bucle de eventos. Lo hacemos al final: obtenemos un bucle de eventos y llamamos a su método run_until_complete. Verás que le pasamos la corrutina principal al bucle de eventos. Esto inicia la ejecución de la corrutina principal, que pone en cola la segunda corrutina y la pone en marcha. A esto se le llama corrutina encadenada.

El problema de este ejemplo es que en realidad no es una corrutina como tal. La razón es que la función download_coroutine no es asíncrona. El problema aquí es que urllib no es asíncrona y, además, no estoy usando await ni yield. Una forma mejor de hacerlo sería utilizar el paquete aiohttp. ¡Veámoslo!

Un mejor ejemplo de corrutina

El paquete aiohttp está diseñado para crear clientes y servidores HTTP asíncronos. Puedes instalarlo con pip así:

pip install aiohttp

Una vez instalado, actualicemos el código para usar aiohttp y poder descargar los archivos:

eyJsYW5ndWFnZSI6InB5dGhvbiIsInNhbXBsZSI6ImltcG9ydCBhaW9odHRwXG5pbXBvcnQgYXN5bmNpb1xuaW1wb3J0IGFzeW5jX3RpbWVvdXRcbmltcG9ydCBvc1xuIFxuYXN5bmMgZGVmIGRvd25sb2FkX2Nvcm91dGluZShzZXNzaW9uLCB1cmwpOlxuICAgIHdpdGggYXN5bmNfdGltZW91dC50aW1lb3V0KDEwKTpcbiAgICAgICAgYXN5bmMgd2l0aCBzZXNzaW9uLmdldCh1cmwpIGFzIHJlc3BvbnNlOlxuICAgICAgICAgICAgZmlsZW5hbWUgPSBfXy5wYXRoLmJhc2VuYW1lKHVybClcbiAgICAgICAgICAgIHdpdGggb3BlbihfX19fX19fXywgJ3diJykgYXMgZl9oYW5kbGU6XG4gICAgICAgICAgICAgICAgd2hpbGUgVHJ1ZTpcbiAgICAgICAgICAgICAgICAgICAgY2h1bmsgPSBhd2FpdCByZXNwb25zZS5jb250ZW50LnJlYWQoMTAyNClcbiAgICAgICAgICAgICAgICAgICAgaWYgbm90IGNodW5rOlxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWtcbiAgICAgICAgICAgICAgICAgICAgZl9oYW5kbGUud3JpdGUoX19fX18pXG4gICAgICAgICAgICByZXR1cm4gYXdhaXQgcmVzcG9uc2UucmVsZWFzZSgpXG4gXG5hc3luYyBkZWYgbWFpbihsb29wKTpcbiAgICB1cmxzID0gW1wiaHR0cDovL3d3dy5pcnMuZ292L3B1Yi9pcnMtcGRmL2YxMDQwLnBkZlwiLFxuICAgICAgICBcImh0dHA6Ly93d3cuaXJzLmdvdi9wdWIvaXJzLXBkZi9mMTA0MGEucGRmXCIsXG4gICAgICAgIFwiaHR0cDovL3d3dy5pcnMuZ292L3B1Yi9pcnMtcGRmL2YxMDQwZXoucGRmXCIsXG4gICAgICAgIFwiaHR0cDovL3d3dy5pcnMuZ292L3B1Yi9pcnMtcGRmL2YxMDQwZXMucGRmXCIsXG4gICAgICAgIFwiaHR0cDovL3d3dy5pcnMuZ292L3B1Yi9pcnMtcGRmL2YxMDQwc2IucGRmXCJdXG4gXG4gICAgYXN5bmMgd2l0aCBhaW9odHRwLkNsaWVudFNlc3Npb24obG9vcD1sb29wKSBhcyBzZXNzaW9uOlxuICAgICAgICB0YXNrcyA9IFtkb3dubG9hZF9jb3JvdXRpbmUoc2Vzc2lvbiwgdXJsKSBmb3IgdXJsIGluIHVybHNdXG4gICAgICAgIGF3YWl0IGFzeW5jaW8uZ2F0aGVyKCp0YXNrcylcbiBcbmlmIF9fbmFtZV9fID09ICdfX21haW5fXyc6XG4gICAgbG9vcCA9IGFzeW5jaW8uZ2V0X2V2ZW50X2xvb3AoKVxuICAgIGxvb3AucnVuX3VudGlsX2NvbXBsZXRlKG1haW4obG9vcCkpIiwic29sdXRpb24iOiJpbXBvcnQgYWlvaHR0cFxuaW1wb3J0IGFzeW5jaW9cbmltcG9ydCBhc3luY190aW1lb3V0XG5pbXBvcnQgb3NcbiBcbmFzeW5jIGRlZiBkb3dubG9hZF9jb3JvdXRpbmUoc2Vzc2lvbiwgdXJsKTpcbiAgICB3aXRoIGFzeW5jX3RpbWVvdXQudGltZW91dCgxMCk6XG4gICAgICAgIGFzeW5jIHdpdGggc2Vzc2lvbi5nZXQodXJsKSBhcyByZXNwb25zZTpcbiAgICAgICAgICAgIGZpbGVuYW1lID0gb3MucGF0aC5iYXNlbmFtZSh1cmwpXG4gICAgICAgICAgICB3aXRoIG9wZW4oZmlsZW5hbWUsICd3YicpIGFzIGZfaGFuZGxlOlxuICAgICAgICAgICAgICAgIHdoaWxlIFRydWU6XG4gICAgICAgICAgICAgICAgICAgIGNodW5rID0gYXdhaXQgcmVzcG9uc2UuY29udGVudC5yZWFkKDEwMjQpXG4gICAgICAgICAgICAgICAgICAgIGlmIG5vdCBjaHVuazpcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgICAgICAgICAgIGZfaGFuZGxlLndyaXRlKGNodW5rKVxuICAgICAgICAgICAgcmV0dXJuIGF3YWl0IHJlc3BvbnNlLnJlbGVhc2UoKVxuIFxuYXN5bmMgZGVmIG1haW4obG9vcCk6XG4gICAgdXJscyA9IFtcImh0dHA6Ly93d3cuaXJzLmdvdi9wdWIvaXJzLXBkZi9mMTA0MC5wZGZcIixcbiAgICAgICAgXCJodHRwOi8vd3d3Lmlycy5nb3YvcHViL2lycy1wZGYvZjEwNDBhLnBkZlwiLFxuICAgICAgICBcImh0dHA6Ly93d3cuaXJzLmdvdi9wdWIvaXJzLXBkZi9mMTA0MGV6LnBkZlwiLFxuICAgICAgICBcImh0dHA6Ly93d3cuaXJzLmdvdi9wdWIvaXJzLXBkZi9mMTA0MGVzLnBkZlwiLFxuICAgICAgICBcImh0dHA6Ly93d3cuaXJzLmdvdi9wdWIvaXJzLXBkZi9mMTA0MHNiLnBkZlwiXVxuIFxuICAgIGFzeW5jIHdpdGggYWlvaHR0cC5DbGllbnRTZXNzaW9uKGxvb3A9bG9vcCkgYXMgc2Vzc2lvbjpcbiAgICAgICAgdGFza3MgPSBbZG93bmxvYWRfY29yb3V0aW5lKHNlc3Npb24sIHVybCkgZm9yIHVybCBpbiB1cmxzXVxuICAgICAgICBhd2FpdCBhc3luY2lvLmdhdGhlcigqdGFza3MpXG4gXG4gXG5pZiBfX25hbWVfXyA9PSAnX19tYWluX18nOlxuICAgIGxvb3AgPSBhc3luY2lvLmdldF9ldmVudF9sb29wKClcbiAgICBsb29wLnJ1bl91bnRpbF9jb21wbGV0ZShtYWluKGxvb3ApKSIsInNjdCI6IkV4KCkudGVzdF9pbXBvcnQoXCJhaW9odHRwXCIpXG5FeCgpLnRlc3RfaW1wb3J0KFwiYXN5bmNpb1wiKVxuRXgoKS50ZXN0X2ltcG9ydChcImFzeW5jX3RpbWVvdXRcIilcbkV4KCkudGVzdF9pbXBvcnQoXCJvc1wiKVxuRXgoKS50ZXN0X3N0dWRlbnRfdHlwZWQoXCJhc3luYyBkZWYgZG93bmxvYWRfY29yb3V0aW5lKHNlc3Npb24sIHVybCk6XCIscGF0dGVybj1GYWxzZSwgbm90X3R5cGVkX21zZz1cIkRpZCB5b3UgZGVmaW5lIGBhc3luYyBkZWYgZG93bmxvYWRfY29yb3V0aW5lYCB0aGF0IHRha2VzIGBzZXNzaW9uYCBhbmQgYHVybGAgYXMgYXJndW1lbnRzP1wiKVxuRXgoKS50ZXN0X3N0dWRlbnRfdHlwZWQoXCJ3aXRoIGFzeW5jX3RpbWVvdXQudGltZW91dCgxMClcIiwgcGF0dGVybj1GYWxzZSxub3RfdHlwZWRfbXNnPVwiRGlkIHlvdSBzZXQgdGhlIGFzeW5jIHRpbWVvdXQgYXQgYDEwYD9cIilcbkV4KCkudGVzdF9zdHVkZW50X3R5cGVkKFwiYXN5bmMgd2l0aCBzZXNzaW9uLmdldCh1cmwpIGFzIHJlc3BvbnNlOlwiLCBwYXR0ZXJuPUZhbHNlLCBub3RfdHlwZWRfbXNnPVwiRGlkIHlvdSBjYWxsIGBzZXNzaW9uYCdzIGBnZXQoKWAgbWV0aG9kIHRvIGdldCB0aGUgYHJlc3BvbnNlYCBvYmplY3QgYmFjaz9cIilcbkV4KCkudGVzdF9zdHVkZW50X3R5cGVkKFwiZmlsZW5hbWUgPSBvcy5wYXRoLmJhc2VuYW1lKHVybClcIixwYXR0ZXJuPUZhbHNlLCBub3RfdHlwZWRfbXNnPVwiRGlkIHlvdSBzcGVjaWZ5IHRoZSBgZmlsZW5hbWVgIHZhcmlhYmxlIHdpdGggdGhlIGhlbHAgb2YgYG9zLnBhdGguYmFzZW5hbWUoKWA/XCIpXG5FeCgpLnRlc3Rfc3R1ZGVudF90eXBlZChcIndpdGggb3BlbihmaWxlbmFtZSwgXFwnd2JcXCcpIGFzIGZfaGFuZGxlOlwiLCBwYXR0ZXJuPUZhbHNlLCBub3RfdHlwZWRfbXNnPVwiRGlkIHlvdSBwYXNzIGBmaWxlbmFtZWAgYW5kIGAnd2InYCB0byBgb3BlbigpYD9cIilcbkV4KCkudGVzdF9zdHVkZW50X3R5cGVkKFwid2hpbGUgVHJ1ZVwiLCBwYXR0ZXJuPUZhbHNlLG5vdF90eXBlZF9tc2c9XCJEaWQgeW91IGxlYXZlIHNvbWV0aGluZyBvdXQgb2YgdGhlIGNvZGU/XCIpXG5FeCgpLnRlc3Rfc3R1ZGVudF90eXBlZChcImNodW5rID0gYXdhaXQgcmVzcG9uc2UuY29udGVudC5yZWFkKDEwMjQpXCIsIHBhdHRlcm49RmFsc2UsIG5vdF90eXBlZF9tc2c9XCJEaWQgeW91IHNwZWNpZnkgdGhlIGBjaHVuayAgdmFyaWFibGU/XCIpXG5FeCgpLnRlc3Rfc3R1ZGVudF90eXBlZChcImlmIG5vdCBjaHVuawpcIiwgcGF0dGVybj1GYWxzZSwgbm90X3R5cGVkX21zZz1cIkRpZCB5b3UgbGVhdmUgc29tZXRoaW5nIG91dCBvZiB0aGUgY29kZT9cIilcbkV4KCkudGVzdF9zdHVkZW50X3R5cGVkKFwiYnJlYWtcIiwgcGF0dGVybj1GYWxzZSxub3RfdHlwZWRfbXNnPVwiRGlkIHlvdSBsZWF2ZSBzb21ldGhpbmcgb3V0IG9mIHRoZSBjb2RlP1wiKVxuRXgoKS50ZXN0X3N0dWRlbnRfdHlwZWQoXCJmX2hhbmRsZS53cml0ZShjaHVuaylcIiwgcGF0dGVybj1GYWxzZSxub3RfdHlwZWRfbXNnPVwiRGlkIHlvdSBwYXNzIGBjaHVuayAgdG8gYGZfaGFuZGxlLndyaXRlKClgP1wiKVxuRXgoKS50ZXN0X3N0dWRlbnRfdHlwZWQoXCJyZXR1cm4gYXdhaXQgcmVzcG9uc2UucmVsZWFzZSgpXCIsIHBhdHRlcm49RmFsc2Usbm90X3R5cGVkX21zZz1cIkRpZCB5b3UgbGVhdmUgc29tZXRoaW5nIG91dCBvZiB0aGUgY29kZT9cIilcbkV4KCkudGVzdF9zdHVkZW50X3R5cGVkKFwiYXN5bmMgZGVmIG1haW4obG9vcCk6XCIsIHBhdHRlcm49RmFsc2Usbm90X3R5cGVkX21zZz1cIkRpZCB5b3UgbGVhdmUgc29tZXRoaW5nIG91dCBvZiB0aGUgY29kZT9cIilcbkV4KCkudGVzdF9zdHVkZW50X3R5cGVkKFwidXJscyA9IFtcXFwiaHR0cDovL3d3dy5pcnMuZ292L3B1Yi9pcnMtcGRmL2YxMDQwLnBkZlxcXCIsXCIscGF0dGVybj1GYWxzZSwgbm90X3R5cGVkX21zZz1cIk1ha2Ugc3VyZSB0byBwYXNzIGF0IGxlYXN0IDEgdXJsIHRvIHRoZSBgdXJsc2AgdmFyaWFibGUhXCIpXG5FeCgpLnRlc3Rfc3R1ZGVudF90eXBlZChcIlxcXCJdXCIsIHBhdHRlcm49RmFsc2UsKVxuRXgoKS50ZXN0X3N0dWRlbnRfdHlwZWQoXCJhc3luYyB3aXRoIGFpb2h0dHAuQ2xpZW50U2Vzc2lvbihsb29wPWxvb3ApIGFzIHNlc3Npb246XCIsIHBhdHRlcm49RmFsc2UsIG5vdF90eXBlZF9tc2c9XCJEaWQgeW91IGxlYXZlIHNvbWV0aGluZyBvdXQgb2YgdGhlIGNvZGU/XCIpXG5FeCgpLnRlc3Rfc3R1ZGVudF90eXBlZChcInRhc2tzID0gW2Rvd25sb2FkX2Nvcm91dGluZShzZXNzaW9uLCB1cmwpIGZvciB1cmwgaW4gdXJsc11cIiwgcGF0dGVybj1GYWxzZSxub3RfdHlwZWRfbXNnPVwiRGlkIHlvdSBsZWF2ZSBzb21ldGhpbmcgb3V0IG9mIHRoZSBjb2RlP1wiKVxuRXgoKS50ZXN0X3N0dWRlbnRfdHlwZWQoXCJhd2FpdCBhc3luY2lvLmdhdGhlcigqdGFza3MpXCIsIHBhdHRlcm49RmFsc2Usbm90X3R5cGVkX21zZz1cIkRpZCB5b3UgbGVhdmUgc29tZXRoaW5nIG91dCBvZiB0aGUgY29kZT9cIilcbkV4KCkudGVzdF9zdHVkZW50X3R5cGVkKFwiaWYgX19uYW1lX18gPT0gXFwnX19tYWluX19cXCc6XCIsIHBhdHRlcm49RmFsc2Usbm90X3R5cGVkX21zZz1cIkRpZCB5b3UgbGVhdmUgc29tZXRoaW5nIG91dCBvZiB0aGUgY29kZT9cIilcbkV4KCkudGVzdF9zdHVkZW50X3R5cGVkKFwibG9vcCA9IGFzeW5jaW8uZ2V0X2V2ZW50X2xvb3AoKVwiLCBwYXR0ZXJuPUZhbHNlLG5vdF90eXBlZF9tc2c9XCJEaWQgeW91IGluaXRpYWxpemUgYSBgbG9vcGAgb2JqZWN0P1wiKVxuRXgoKS50ZXN0X3N0dWRlbnRfdHlwZWQoXCJsb29wLnJ1bl91bnRpbF9jb21wbGV0ZShtYWluKGxvb3ApKVwiLCBwYXR0ZXJuPUZhbHNlLG5vdF90eXBlZF9tc2c9XCJEaWQgeW91IGxlYXZlIHNvbWV0aGluZyBvdXQgb2YgdGhlIGNvZGU/XCIpXG5zdWNjZXNzX21zZyhcIldlbGwgZG9uZSEgWW91IGhhdmUgbm93IGRvd25sb2FkZWQgdGhlIGZpbGVzIHdpdGggdGhlIGBhaW9odHRwYCBwYWNrYWdlIVwiKSJ9

Verás que importamos un par de elementos nuevos: aiohttp y async_timeout. Este último es en realidad una dependencia de aiohttp y nos permite crear un gestor de contexto de tiempo de espera. Empecemos por la parte inferior del código y vayamos hacia arriba. En la condición final, iniciamos el bucle de eventos asíncrono y llamamos a nuestra función principal.

En la función principal, creamos un objeto ClientSession que pasamos a nuestra función corrutina de descarga para cada una de las URLs que queremos descargar. En download_coroutine, creamos un gestor de contexto async_timeout.timeout() que básicamente inicia un temporizador de X segundos. Cuando el tiempo se agota, el gestor de contexto finaliza o expira. En este caso, el tiempo de espera es de 10 segundos. A continuación, llamamos al método get() de la sesión, que nos da un objeto respuesta. Aquí llega la parte un poco mágica. Cuando usas el atributo content del objeto respuesta, devuelve una instancia de aiohttp.StreamReader, que nos permite descargar el archivo por bloques del tamaño que queramos. A medida que leemos el archivo, lo escribimos en disco local. Por último, llamamos al método release() de la respuesta, que finaliza su procesamiento.

Según la documentación de aiohttp, como el objeto respuesta se creó dentro de un gestor de contexto, técnicamente se llama a release() de forma implícita. Pero en Python, lo explícito suele ser mejor, y la documentación indica que no deberíamos confiar en que la conexión se cierre sin más, así que creo que en este caso es mejor liberarla explícitamente.

Hay una parte que sigue bloqueando: la escritura en disco. Mientras escribimos el archivo, seguimos bloqueando. Existe otra biblioteca, aiofiles, que podríamos usar para intentar que la escritura sea también asíncrona, pero dejo esa mejora a quien lea esto.

Planificación de llamadas

También puedes planificar llamadas a funciones normales usando el bucle de eventos de asyncio. El primer método que veremos es call_soon. Este método llamará a tu callback o gestor de eventos en cuanto pueda. Funciona como una cola FIFO, así que si algunas devoluciones de llamada tardan en ejecutarse, las siguientes se retrasarán hasta que las anteriores finalicen.

Veamos un ejemplo:

eyJsYW5ndWFnZSI6InB5dGhvbiIsInNhbXBsZSI6ImltcG9ydCBfX19fX19cbmltcG9ydCBmdW5jdG9vbHNcbiBcbmRlZiBldmVudF9oYW5kbGVyKGxvb3AsIHN0b3A9RmFsc2UpOlxuICAgIHByaW50KCdFdmVudCBoYW5kbGVyIGNhbGxlZCcpXG4gICAgaWYgc3RvcDpcbiAgICAgICAgcHJpbnQoJ3N0b3BwaW5nIHRoZSBsb29wJylcbiAgICAgICAgbG9vcC5zdG9wKClcblxuaWYgX19uYW1lX18gPT0gJ19fbWFpbl9fJzpcbiAgICBsb29wID0gYXN5bmNpby5nZXRfZXZlbnRfbG9vcCgpXG4gICAgdHJ5OlxuICAgICAgICBsb29wLmNhbGxfc29vbihmdW5jdG9vbHMucGFydGlhbChfX19fX19fX19fX19fLCBfX19fKSlcbiAgICAgICAgcHJpbnQoJ3N0YXJ0aW5nIGV2ZW50IGxvb3AnKVxuICAgICAgICBsb29wLmNhbGxfc29vbihmdW5jdG9vbHMucGFydGlhbChfX19fX19fX19fX19fLCBfX19fLCBzdG9wPVRydWUpKVxuIFxuICAgICAgICBsb29wLl9fX19fX19fX18oKVxuICAgIGZpbmFsbHk6XG4gICAgICAgIHByaW50KCdjbG9zaW5nIGV2ZW50IGxvb3AnKVxuICAgICAgICBsb29wLl9fX19fKCkiLCJzb2x1dGlvbiI6ImltcG9ydCBhc3luY2lvXG5pbXBvcnQgZnVuY3Rvb2xzXG4gXG5kZWYgZXZlbnRfaGFuZGxlcihsb29wLCBzdG9wPUZhbHNlKTpcbiAgICBwcmludCgnRXZlbnQgaGFuZGxlciBjYWxsZWQnKVxuICAgIGlmIHN0b3A6XG4gICAgICAgIHByaW50KCdzdG9wcGluZyB0aGUgbG9vcCcpXG4gICAgICAgIGxvb3Auc3RvcCgpXG5cbmlmIF9fbmFtZV9fID09ICdfX21haW5fXyc6XG4gICAgbG9vcCA9IGFzeW5jaW8uZ2V0X2V2ZW50X2xvb3AoKVxuICAgIHRyeTpcbiAgICAgICAgbG9vcC5jYWxsX3Nvb24oZnVuY3Rvb2xzLnBhcnRpYWwoZXZlbnRfaGFuZGxlciwgbG9vcCkpXG4gICAgICAgIHByaW50KCdzdGFydGluZyBldmVudCBsb29wJylcbiAgICAgICAgbG9vcC5jYWxsX3Nvb24oZnVuY3Rvb2xzLnBhcnRpYWwoZXZlbnRfaGFuZGxlciwgbG9vcCwgc3RvcD1UcnVlKSlcbiBcbiAgICAgICAgbG9vcC5ydW5fZm9yZXZlcigpXG4gICAgZmluYWxseTpcbiAgICAgICAgcHJpbnQoJ2Nsb3NpbmcgZXZlbnQgbG9vcCcpXG4gICAgICAgIGxvb3AuY2xvc2UoKSIsInNjdCI6IkV4KCkudGVzdF9pbXBvcnQoXCJhc3luY2lvXCIpXG5FeCgpLnRlc3RfaW1wb3J0KFwiZnVuY3Rvb2xzXCIpXG5FeCgpLnRlc3RfZnVuY3Rpb25fZGVmaW5pdGlvbihcImV2ZW50X2hhbmRsZXJcIilcbkV4KCkudGVzdF9zdHVkZW50X3R5cGVkKFwiaWYgX19uYW1lX18gPT0gXFwnX19tYWluX19cXCc6XCIsIHBhdHRlcm49RmFsc2UsIG5vdF90eXBlZF9tc2c9XCJEaWQgeW91IHJlbW92ZSBzb21ldGhpbmcgZnJvbSB0aGUgY29kZTE/XCIpXG5FeCgpLnRlc3Rfc3R1ZGVudF90eXBlZChcImxvb3AgPSBhc3luY2lvLmdldF9ldmVudF9sb29wKClcIiwgcGF0dGVybj1GYWxzZSxub3RfdHlwZWRfbXNnPVwiRGlkIHlvdSBhc3NpZ24gYGFzeW5jaW8uZ2V0X2V2ZW50X2xvb3AoKWAgdG8gYGxvb3BgP1wiKVxuRXgoKS50ZXN0X3N0dWRlbnRfdHlwZWQoXCJ0cnk6XCIsIHBhdHRlcm49RmFsc2Usbm90X3R5cGVkX21zZz1cIkRpZCB5b3UgYWRkIGB0cnlgIHRvIHRoZSBjb2RlP1wiKVxuRXgoKS50ZXN0X3N0dWRlbnRfdHlwZWQoXCJsb29wLmNhbGxfc29vbihmdW5jdG9vbHMucGFydGlhbChldmVudF9oYW5kbGVyLCBsb29wKSlcIiwgcGF0dGVybj1GYWxzZSwgbm90X3R5cGVkX21zZz1cIkRpZCB5b3UgcGFzcyBgZXZlbnRfaGFuZGxlcmAgYW5kIGBsb29wYCB0byBgbG9vcC5jYWxsX3Nvb24oZnVuY3Rvb2xzLnBhcnRpYWwoKSlgP1wiKVxuRXgoKS50ZXN0X3N0dWRlbnRfdHlwZWQoXCJsb29wLmNhbGxfc29vbihmdW5jdG9vbHMucGFydGlhbChldmVudF9oYW5kbGVyLCBsb29wLCBzdG9wPVRydWUpKVwiLCBwYXR0ZXJuPUZhbHNlLCBub3RfdHlwZWRfbXNnPVwiRGlkIHlvdSBwYXNzIGBldmVudF9oYW5kbGVyYCBhbmQgYGxvb3BgIHRvIGBsb29wLmNhbGxfc29vbihmdW5jdG9vbHMucGFydGlhbCgpKWA/IERvbid0IGZvcmdldCB0byBrZWVwIGBzdG9wYCBzZXQgdG8gYFRydWVgIVwiKVxuRXgoKS50ZXN0X3N0dWRlbnRfdHlwZWQoXCJsb29wLnJ1bl9mb3JldmVyKClcIiwgcGF0dGVybj1GYWxzZSxub3RfdHlwZWRfbXNnPVwiRGlkIHlvdSBhZGQgYGxvb3AucnVuX2ZvcmV2ZXIoKWAgdG8gdGhlIGNvZGU/XCIpXG5FeCgpLnRlc3Rfc3R1ZGVudF90eXBlZChcImZpbmFsbHk6XCIsIHBhdHRlcm49RmFsc2Usbm90X3R5cGVkX21zZz1cIkRpZCB5b3UgYWRkIGBmaW5hbGx5YCB0byB0aGUgY29kZT9cIilcbkV4KCkudGVzdF9zdHVkZW50X3R5cGVkKFwibG9vcC5jbG9zZSgpXCIsIHBhdHRlcm49RmFsc2Usbm90X3R5cGVkX21zZz1cIkRpZCB5b3UgY2xvc2UgYGxvb3BgP1wiKVxuc3VjY2Vzc19tc2coXCJZb3UgaGF2ZSBub3cgc3VjY2Vzc2Z1bGx5IGxlYXJuZWQgaG93IHRvIHNjaGVkdWxlIGNhbGxzIHdpdGggdGhlIGFzeW5jaW8gZXZlbnQgbG9vcCFcIikifQ==

La mayoría de las funciones de asyncio no aceptan palabras clave, así que necesitaremos el módulo functools si queremos pasarlas a nuestro gestor de eventos. Nuestra función normal imprimirá texto por stdout cada vez que se llame. Si estableces su argumento stop en True, también detendrá el bucle de eventos.

La primera vez que la llamamos no detenemos el bucle. La segunda vez, sí. Queremos detenerlo porque le hemos indicado que haga run_forever, lo que pone el bucle en un ciclo infinito. Una vez detenido, podemos cerrarlo.

Si ejecutas este código, verás una salida como esta:

starting event loop
Event handler called
Event handler called
stopping the loop
closing event loop

Existe una función relacionada llamada call_soon_threadsafe. Como su nombre indica, funciona igual que call_soon, pero es segura para hilos. Si quieres retrasar una llamada hasta algún momento futuro, puedes usar la función call_later. En este caso, podríamos cambiar la firma de call_soon por la siguiente:

loop.call_later(1, event_handler, loop)

Esto retrasará la llamada a nuestro gestor de eventos un segundo; después lo llamará y le pasará el bucle como primer parámetro. Si quieres planificar un momento concreto en el futuro, tendrás que obtener el tiempo del propio bucle en lugar del tiempo del sistema. Puedes hacerlo así:

current_time = loop.time()

Con eso, basta con usar la función call_at y pasarle el instante en el que quieres que se llame a tu gestor de eventos. Por ejemplo, si queremos llamarlo dentro de cinco minutos, podríamos hacerlo así:

loop.call_at(current_time + 300, event_handler, loop)

En este ejemplo usamos el tiempo actual que hemos obtenido y le sumamos 300 segundos (cinco minutos). De esta forma, ¡retrasamos la llamada a nuestro gestor de eventos cinco minutos! ¡Nada mal!

Tareas

Las tareas (Tasks) son una subclase de Future y un contenedor alrededor de una corrutina. Te permiten llevar un seguimiento de cuándo terminan de procesarse. Como son un tipo de Future, otras corrutinas pueden esperar a una tarea y también puedes obtener el resultado de una tarea cuando haya finalizado.

Veamos un ejemplo sencillo:

eyJsYW5ndWFnZSI6InB5dGhvbiIsInNhbXBsZSI6ImltcG9ydCBfX19fX19fXG5cbmFzeW5jIGRlZiBteV90YXNrKHNlY29uZHMpOlxuICAgIFwiXCJcIlxuICAgIEEgdGFzayB0byBkbyBmb3IgYSBudW1iZXIgb2Ygc2Vjb25kc1xuICAgIFwiXCJcIlxuICAgIHByaW50KCdUaGlzIHRhc2sgaXMgdGFraW5nIHt9IHNlY29uZHMgdG8gY29tcGxldGUnLmZvcm1hdChcbiAgICAgICAgc2Vjb25kcykpXG4gICAgYXdhaXQgYXN5bmNpby5zbGVlcChfX19fX19fKVxuICAgIHJldHVybiAndGFzayBmaW5pc2hlZCdcbiBcbiBcbmlmIF9fbmFtZV9fID09ICdfX21haW5fXyc6XG4gICAgbXlfZXZlbnRfbG9vcCA9IGFzeW5jaW8uZ2V0X2V2ZW50X2xvb3AoKVxuICAgIHRyeTpcbiAgICAgICAgcHJpbnQoJ3Rhc2sgY3JlYXRpb24gc3RhcnRlZCcpXG4gICAgICAgIHRhc2tfb2JqID0gbXlfZXZlbnRfbG9vcC5jcmVhdGVfdGFzayhteV90YXNrKHNlY29uZHM9MikpXG4gICAgICAgIG15X2V2ZW50X2xvb3AucnVuX3VudGlsX2NvbXBsZXRlKHRhc2tfb2JqKVxuICAgIGZpbmFsbHk6XG4gICAgICAgIG15X2V2ZW50X2xvb3AuX19fX18oKVxuIFxuICAgIHByaW50KFwiVGhlIHRhc2sncyByZXN1bHQgd2FzOiB7fVwiLmZvcm1hdCh0YXNrX29iai5yZXN1bHQoKSkpIiwic29sdXRpb24iOiJpbXBvcnQgYXN5bmNpb1xuXG5hc3luYyBkZWYgbXlfdGFzayhzZWNvbmRzKTpcbiAgICBcIlwiXCJcbiAgICBBIHRhc2sgdG8gZG8gZm9yIGEgbnVtYmVyIG9mIHNlY29uZHNcbiAgICBcIlwiXCJcbiAgICBwcmludCgnVGhpcyB0YXNrIGlzIHRha2luZyB7fSBzZWNvbmRzIHRvIGNvbXBsZXRlJy5mb3JtYXQoc2Vjb25kcykpXG4gICAgYXdhaXQgYXN5bmNpby5zbGVlcChzZWNvbmRzKVxuICAgIHJldHVybiAndGFzayBmaW5pc2hlZCdcbiBcbiBcbmlmIF9fbmFtZV9fID09ICdfX21haW5fXyc6XG4gICAgbXlfZXZlbnRfbG9vcCA9IGFzeW5jaW8uZ2V0X2V2ZW50X2xvb3AoKVxuICAgIHRyeTpcbiAgICAgICAgcHJpbnQoJ3Rhc2sgY3JlYXRpb24gc3RhcnRlZCcpXG4gICAgICAgIHRhc2tfb2JqID0gbXlfZXZlbnRfbG9vcC5jcmVhdGVfdGFzayhteV90YXNrKHNlY29uZHM9MikpXG4gICAgICAgIG15X2V2ZW50X2xvb3AucnVuX3VudGlsX2NvbXBsZXRlKHRhc2tfb2JqKVxuICAgIGZpbmFsbHk6XG4gICAgICAgIG15X2V2ZW50X2xvb3AuY2xvc2UoKVxuIFxuICAgIHByaW50KFwiVGhlIHRhc2sncyByZXN1bHQgd2FzOiB7fVwiLmZvcm1hdCh0YXNrX29iai5yZXN1bHQoKSkpIiwic2N0IjoiRXgoKS50ZXN0X2ltcG9ydChcImFzeW5jaW9cIilcbkV4KCkudGVzdF9zdHVkZW50X3R5cGVkKFwiYXN5bmMgZGVmIG15X3Rhc2soc2Vjb25kcyk6XCIsIHBhdHRlcm49RmFsc2UsIG5vdF90eXBlZF9tc2c9XCJEaWQgeW91IGRlZmluZSB0aGUgYXN5bmMgZnVuY3Rpb24gYG15X3Rhc2soKWA/XCIpXG5FeCgpLnRlc3Rfc3R1ZGVudF90eXBlZChcImF3YWl0IGFzeW5jaW8uc2xlZXAoc2Vjb25kcylcIiwgcGF0dGVybj1GYWxzZSwgbm90X3R5cGVkX21zZz1cIkRpZCB5b3UgcGFzcyBgc2Vjb25kc2AgdG8gYGFzeW5jaW8uc2xlZXAoKWA/XCIpXG5FeCgpLnRlc3Rfc3R1ZGVudF90eXBlZChcInJldHVybiBcXCd0YXNrIGZpbmlzaGVkXFwnXCIsIHBhdHRlcm49RmFsc2UsIG5vdF90eXBlZF9tc2c9XCJEaWQgeW91IHJldHVybiBcXCd0YXNrIGZpbmlzaGVkXFwnP1wiKVxuRXgoKS50ZXN0X3N0dWRlbnRfdHlwZWQoXCJpZiBfX25hbWVfXyA9PSBcXCdfX21haW5fX1xcJzpcIiwgcGF0dGVybj1GYWxzZSwgbm90X3R5cGVkX21zZz1cIkRpZCB5b3UgcmVtb3ZlIHNvbWV0aGluZyBmcm9tIHRoZSBjb2RlP1wiKVxuRXgoKS50ZXN0X3N0dWRlbnRfdHlwZWQoXCJteV9ldmVudF9sb29wID0gYXN5bmNpby5nZXRfZXZlbnRfbG9vcCgpXCIsIHBhdHRlcm49RmFsc2UsIG5vdF90eXBlZF9tc2c9XCJEaWQgeW91IGdldCB0aGUgZXZlbnQgbG9vcCB3aXRoIGBnZXRfZXZlbnRfbG9vcCgpYCBhbmQgYXNzaWduIGl0IHRvIGBteV9ldmVudF9sb29wYD9cIilcbkV4KCkudGVzdF9zdHVkZW50X3R5cGVkKFwidHJ5OlwiLCBwYXR0ZXJuPUZhbHNlLCBub3RfdHlwZWRfbXNnPVwiRGlkIHlvdSBhZGQgYHRyeWAgdG8gdGhlIGNvZGUgY2h1bms/XCIpXG5FeCgpLnRlc3Rfc3R1ZGVudF90eXBlZChcInRhc2tfb2JqID0gbXlfZXZlbnRfbG9vcC5jcmVhdGVfdGFzayhteV90YXNrKHNlY29uZHM9MikpXCIsIHBhdHRlcm49RmFsc2UsIG5vdF90eXBlZF9tc2c9XCJEaWQgeW91IGNyZWF0ZSBhIHRhc2sgZm9yIGBteV9ldmVudF9sb29wYCB3aXRoIGBjcmVhdGVfdGFza2A/IEFsc28gZG9uJ3QgZm9yZ2V0IHRvIHBhc3MgYG15X3Rhc2soc2Vjb25kcz0yKWAgdG8gdGhlIGZ1bmN0aW9uIVwiKVxuRXgoKS50ZXN0X3N0dWRlbnRfdHlwZWQoXCJteV9ldmVudF9sb29wLnJ1bl91bnRpbF9jb21wbGV0ZSh0YXNrX29iailcIiwgcGF0dGVybj1GYWxzZSwgbm90X3R5cGVkX21zZz1cIkRpZCB5b3UgYWRkIGBteV9ldmVudF9sb29wLnJ1bl91bnRpbF9jb21wbGV0ZSh0YXNrX29iaikgdG8gdGhlIGNvZGUgY2h1bms/XCIpXG5FeCgpLnRlc3Rfc3R1ZGVudF90eXBlZChcImZpbmFsbHk6XCIsIHBhdHRlcm49RmFsc2UsIG5vdF90eXBlZF9tc2c9XCJEaWQgeW91IHNwZWNpZnkgYGZpbmFsbHlgP1wiKVxuRXgoKS50ZXN0X3N0dWRlbnRfdHlwZWQoXCJteV9ldmVudF9sb29wLmNsb3NlKClcIiwgcGF0dGVybj1GYWxzZSwgbm90X3R5cGVkX21zZz1cIkRpZCB5b3UgY2xvc2UgYG15X2V2ZW50X2xvb3BgIHdpdGggYGNsb3NlKClgP1wiKVxuc3VjY2Vzc19tc2coXCJDb25ncmF0cyEhIFlvdSBoYXZlIGNyZWF0ZWQgYW4gYXN5bmMgZnVuY3Rpb24gdGhhdCBhY2NlcHRzIHRoZSBudW1iZXIgb2Ygc2Vjb25kcyBpdCB3aWxsIHRha2UgZm9yIHRoZSBmdW5jdGlvbiB0byBydW4hXCIpfQ==

Aquí creamos una función asíncrona que recibe el número de segundos que tardará en ejecutarse, lo que simula un proceso de larga duración. Luego creamos el bucle de eventos y un objeto tarea llamando a la función create_task del bucle. create_task acepta la función que queremos convertir en tarea. Después indicamos al bucle que se ejecute hasta que la tarea termine. Al final, obtenemos el resultado de la tarea, ya que habrá finalizado.

Las tareas también pueden cancelarse fácilmente con su método cancel. Cuando quieras terminar una tarea, llámalo. Si una tarea se cancela mientras está esperando otra operación, lanzará una CancelledError.

Para terminar

A estas alturas deberías saber lo suficiente como para empezar a trabajar por tu cuenta con la biblioteca asyncio. Es muy potente y te permite hacer un montón de tareas interesantes. La biblioteca asyncio se diseñó para sockets de red.

Una gran biblioteca que permitía programación asíncrona con sockets antes de asyncio es el framework Twisted. Otro proyecto interesante es Dask, una biblioteca flexible de computación paralela para análisis. Investiga la documentación del módulo asyncio y deja que fluyan las ideas.

Temas
Python

Cursos de Python

Curso

Introducción a Python

4 h
7M
Domina los fundamentos del análisis de datos con Python en cuatro horas y descubre sus paquetes más usados.
Ver detallesRight Arrow
Iniciar Curso
Ver másRight Arrow
Relacionado

Tutorial

Tutorial de FastAPI: Introducción al uso de FastAPI

Explore el marco FastAPI y descubra cómo puede utilizarlo para crear API en Python.
Moez Ali's photo

Moez Ali

13 min

Tutorial

Multiprocesamiento en Python: Guía de hilos y procesos

Aprende a gestionar hilos y procesos con el módulo de multiprocesamiento de Python. Descubre las técnicas clave de la programación paralela. Mejora la eficacia de tu código con ejemplos.
Kurtis Pykes 's photo

Kurtis Pykes

7 min

Tutorial

Guía completa de programación de sockets en Python

Aprende los fundamentos de la programación de sockets en Python
Serhii Orlivskyi's photo

Serhii Orlivskyi

15 min

Tutorial

Una Introducción al Subproceso Python: Conceptos básicos y ejemplos

Explora nuestra guía paso a paso para ejecutar comandos externos utilizando el módulo de subprocesos de Python, completa con ejemplos.
Moez Ali's photo

Moez Ali

15 min

Tutorial

Desarrollo backend con Python: guía completa para principiantes

Esta guía completa te enseña los fundamentos del backend con Python. Aprende conceptos básicos, frameworks y buenas prácticas para empezar a crear aplicaciones web.
Oluseye Jeremiah's photo

Oluseye Jeremiah

15 min

Tutorial

APIs Web, Peticiones en Python y Realización de una Petición HTTP en el Tutorial de Python

Conoce los fundamentos de HTTP y también la biblioteca de peticiones en Python para realizar distintos tipos de peticiones.
Kurtis Pykes 's photo

Kurtis Pykes

15 min

Ver MásVer Más