SlideShare una empresa de Scribd logo
PEP-3156
Async I/O en Python
Saúl Ibarra Corretgé
@saghul

PyConES 2013
Sunday, November 24, 13
repr(self)
>>> from Amsterdam import saghul
>>> saghul.work()
VoIP, SIP, XMPP, chat, Real Time Communications
>>> saghul.other()
networking, event loops, sockets, MOAR PYTHON
>>> saghul.languages()
Python, C
>>> saghul.message()
Estoy encantado de participar en PyConES!
>>>

Sunday, November 24, 13
import open_source

• Core Team de libuv
• Tulip / asyncio
• Muchos experimentos con event
loops y más cosas

•

Sunday, November 24, 13

github.com/saghul
import socket
import socket
server = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
server.bind(('127.0.0.1', 1234))
server.listen(128)
print("Server listening on: {}".format(server.getsockname()))
client, addr = server.accept()
print("Client connected: {}".format(addr))
while True:
data = client.recv(4096)
if not data:
print("Client has disconnected")
break
client.send(data)
server.close()

Sunday, November 24, 13
except Exception

• Solo podemos gestionar una conexión
• Soluciones para soportar múltiples
clientes

• Threads
• Procesos
• Multiplexores de I/O
Sunday, November 24, 13
import thread
import socket
import thread
def handle_client(client, addr):
print("Client connected: {}".format(addr))
while True:
data = client.recv(4096)
if not data:
print("Client has disconnected")
break
client.send(data)
server = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
server.bind(('127.0.0.1', 1234))
server.listen(128)
print("Server listening on: {}".format(server.getsockname()))
while True:
client, addr = server.accept()
thread.start_new_thread(handle_client, (client, addr))

Sunday, November 24, 13
except Exception

• Los threads añaden overhead
•
•

Tamaño del stack
Cambios de contexto

• Sincronización entre threads
• El GIL - NO es un problema
Sunday, November 24, 13
Multiplexores de I/O

• Examinar y bloquearse a la espera de
que un fd esté listo

• ¡Aun así la operación puede bloquear!
• El fd tiene que ser puesto en modo no
bloqueante

• ¿Y Windows?
Sunday, November 24, 13
Sunday, November 24, 13
Multiplexores de I/O
1. Poner un fd en modo no bloqueante
2. Añadir el fd al multiplexor
3. Esperar un rato
4. Realizar la operación bloqueante sobre
el fd si está listo

Sunday, November 24, 13
def set_nonblocking
import fcntl
def set_nonblocking(fdobj):
# unix only
try:
setblocking = fdobj.setblocking
except AttributeError:
try:
fd = fdobj.fileno()
except AttributeError:
fd = fdobj
flags = fcntl.fcntl(fd, fcntl.F_GETFL)
fcntl.fcntl(fd, fcntl.F_SETFL, flags | os.O_NONBLOCK)
else:
setblocking(False)

Sunday, November 24, 13
import select

• El módulo “select” implementa los
distintos multiplexores de i/o

•
•
•
•

select
poll
kqueue
epoll

• En Python 3.4, módulo “selectors”
Sunday, November 24, 13
sys.platform == ‘win32’

• Soporta select()!
• 64 fds por thread
• >= Vista soporta WSAPoll!
• Está roto: bit.ly/Rg06jX
• IOCP es lo que mola
Sunday, November 24, 13
import IOCP

• Empezar la operación de i/o en modo
overlapped

• Recibe un callback cuando ha
terminado

• Completion Ports
• Abstracción totalmente distinta a Unix
Sunday, November 24, 13
windows.rules = True

Sunday, November 24, 13
Sunday, November 24, 13
Frameworks

• Los frameworks nos abstraen de las
diferentes plataformas

• Protocolos
• Integracion con otros event loops: Qt,
GLib, ...

• Distintas APIs
Sunday, November 24, 13
import twisted

• Usa select, poll, kqueue, epoll del
módulo select

• IOCP en Windows
• Integración con otros loops como Qt
• Protocolos, transportes, ...
• Deferred
Sunday, November 24, 13
import tornado

• Usa select, poll, kqueue, epoll del
modulo select

• select() en Windows :-(
• Principalmente orientado a desarrollo
web

• API
Sunday, November 24, 13

síncrona con coroutines
import gevent

• Usa libevent en la 0.x y libev en la 1.x
• select() en Windows :-(
• API síncrona con greenlet

Sunday, November 24, 13
import asyncore

• raise RuntimeError(“NOT GOOD ENOUGH”)
• “asyncore: included batteries don’t fit”
bit.ly/182HcHT

Sunday, November 24, 13
Solución

Sunday, November 24, 13
I’m not trying to reinvent the
wheel. I’m trying to build a
good one.
Guido van Rossum

Sunday, November 24, 13
asyncio

import tulip
Sunday, November 24, 13
import asyncio

• Implementación de referencia del
PEP-3156

• Componentes base para i/o asíncrona
• Funciona en Python >= 3.3

Sunday, November 24, 13
Objetivos

• Implementación moderna de i/o asíncrona
para Python

• Utilizar yield from (PEP-380)
•

Pero no obligar a nadie

• No utilizar nada que requiera Python > 3.3
• Interoprabilidad con otros frameworks
Sunday, November 24, 13
Objetivos

• Soporte para Unix y Windows
• IPv4 e IPv6
• TCP, UDP y pipes
• SSL básico (seguro por defecto)
• Subprocesos
Sunday, November 24, 13
No Objetivos

• Perfección
• Reemplazar los frameworks actuales
• Implementaciones de protocolos
concretos

• Reemplazar httplib, smtplib, ...
• Funcionar en Python < 3.3
Sunday, November 24, 13
¿Interoperabilidad?

twisted

tornado

gevent

...

asyncio
selectors

Sunday, November 24, 13

iocp
¿Interoperabilidad?

twisted

tornado

gevent

asyncio
rose / pyuv

Sunday, November 24, 13

...
Arquitectura
Sunday, November 24, 13
Componentes
Event loop, policy

Coroutines, Futures, Tasks

Transports, Protocols

Sunday, November 24, 13
Event loop
Sunday, November 24, 13
Event loop y policy

• Selecciona el mejor selector para cada
plataforma

• APIs para crear servidores y
conexiones (TCP, UDP, ...)

Sunday, November 24, 13
Callbacks

• loop.call_soon(func, *args)
• loop.call_later(delay, func, *args)
• loop.call_at(when, func, *args)
• loop.time()
Sunday, November 24, 13
Callbacks para I/O

• loop.add_reader(fd, func, *args)
• loop.add_writer(fd, func, *args)
• loop.remove_reader(fd)
• loop.remove_writer(fd)
Sunday, November 24, 13
Señales Unix

• loop.add_signal_handler(sig, func, *args)
• loop.remove_signal_handler(sig)

Sunday, November 24, 13
Interfaz con Threads

• loop.call_soon_threadsafe(func, *args)
• loop.run_in_executor(exc, func, *args)
• loop.set_default_executor(exc)

Sunday, November 24, 13
Inicio y parada

• loop.run_forever()
• loop.stop()
• loop.run_until_complete(f)

Sunday, November 24, 13
Acceso a la instancia

• get_event_loop()
• set_event_loop(loop)
• new_event_loop()

Sunday, November 24, 13
Policy (default)

• Un event loop por thread
• Solo se crea un loop automágicamente
para el main thread

Sunday, November 24, 13
Policy

• Configura qué hacen get/set/new
_event_loop

• Es el único objeto global
• ¡Se puede cambiar! (ejemplo: rose)

Sunday, November 24, 13
Coroutines, Futures y
Tasks
Sunday, November 24, 13
Coroutines, Futures y Tasks

• Coroutines
•
•

una función generator, puede recibir valores

•

promesa de resultado o error

•

Future que ejecuta una coroutine

decorada con @coroutine

• Future
• Task
Sunday, November 24, 13
Coroutines y yield from
import asyncio
import socket
loop = asyncio.get_event_loop()
@asyncio.coroutine
def handle_client(client, addr):
print("Client connected: {}".format(addr))
while True:
data = yield from loop.sock_recv(client, 4096)
if not data:
print("Client has disconnected")
break
client.send(data)
@asyncio.coroutine
def accept_connections(server_socket):
while True:
client, addr = yield from loop.sock_accept(server_socket)
asyncio.async(handle_client(client, addr))
server = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM)
server.bind(('127.0.0.1', 1234))
server.listen(128)
server.setblocking(False)
print("Server listening on: {}".format(server.getsockname()))
loop.run_until_complete(accept_connections(server))

Sunday, November 24, 13
Coroutines y yield from

• Imagina que el yield from no existe
• Imagina que el código es secuencial
• No te bases en la definición formal de
yield from (PEP-380)

Sunday, November 24, 13
Futures

• Parecidos a los Futures de PEP-3148
•

concurrent.futures.Future

•
•
•
•
•

f.set_result(); r = f.result()

• API (casi) idéntico:

Sunday, November 24, 13

f.set_exception(e); e = f.exception()
f.done()
f.add_done_callback(x); f.remove_done_callback(x)
f.cancel(); f.cancelled()
Futures + Coroutines

• yield from funciona con los Futures!
•
•

f = Future()

•

Alguien pondrá el resultado o la excepción luego

r = yield from f

•

Espera a que esté listo y devuelve f.result()

• Normalmente devueltos por funciones
Sunday, November 24, 13
Deshaciendo callbacks
@asyncio.coroutine
def sync_looking_function(*args):
fut = asyncio.Future()
def cb(result, error):
if error is not None:
fut.set_result(result)
else:
fut.set_exception(Exception(error))
async_function(cb, *args)
return (yield from fut)

Sunday, November 24, 13
Tasks

• Unicornios con polvo de hada
• Es una coroutine metida en un Future
• WAT
• Hereda de Future
• Funciona con yield from
•

Sunday, November 24, 13

r = yield from Task(coro(...))
Tasks vs coroutines

• Una coroutine no “avanza” sin un
mechanismo de scheduling

• Los Tasks pueden avanzar solos, sin
necesidad de esperar

• El event loop es el scheduler!
•

Sunday, November 24, 13

Magia!
Otro ejemplo
import asyncio
loop = asyncio.get_event_loop()
clients = {} # task -> (reader, writer)
def _accept_client(client_reader, client_writer):
task = asyncio.Task(_handle_client(client_reader, client_writer))
clients[task] = (client_reader, client_writer)
def client_done(task):
del clients[task]
task.add_done_callback(client_done)
@asyncio.coroutine
def _handle_client(client_reader, client_writer):
while True:
data = (yield from client_reader.readline())
client_writer.write(data)

f = asyncio.start_server(_accept_client, '127.0.0.1', 12345)
server = loop.run_until_complete(f)
loop.run_forever()

Sunday, November 24, 13
Transports y Protocols
Sunday, November 24, 13
Transports y Protocols

• Transport: representa una conexión
(socket, pipe, ...)

• Protocol: representa una aplicación
(servidor HTTP, cliente IRC, ...)

• Siempre van juntos
• API basada en llamadas a función y
callbacks

Sunday, November 24, 13
Clientes y servidores

• loop.create_connection(...)
•

crea un Transport y un Protocol

•

crea un Transport y un Protocol por cada
conexión aceptada

•

devuelve un objeto Server

• loop.create_server(...)

Sunday, November 24, 13
Clientes y servidores

• loop.open_connection(...)
•

wrapper sobre create_connection, devuelve
(stream_reader, stream_writer)

• loop.start_server(...)
•

Sunday, November 24, 13

wrapper sobre create_server, ejecuta un
callback con (stream_reader, stream_writer)
por cada conexión aceptada
Interfaz Transport -> Protocol

• connection_made(transport)
• data_received(data)
• eof_received()
• connection_lost(exc)
Sunday, November 24, 13
Interfaz Protocol -> Transport

• write(data)
• writelines(seq)
• write_eof()
• close()
• abort()
Sunday, November 24, 13
MOAR PROTOCOL!

• ¡Esta tarde a las 17:30!
• “Tulip or not Tulip” - Iñaki Galarza

Sunday, November 24, 13
¿Y ahora qué?

• Ven a la charla de Iñaki
• Lee el PEP-3156
• Implementa algún protocolo sencillo
(cliente IRC por ejemplo)

• ¡Usa asyncio en tu próximo proyecto!
Sunday, November 24, 13
¿Preguntas?

@saghul
bettercallsaghul.com
Sunday, November 24, 13
Referencias

• code.google.com/p/tulip/
• groups.google.com/forum/#!forum/
python-tulip

• PEP-3156
• http://www.youtube.com/watch?
v=1coLC-MUCJc

• https://www.dropbox.com/s/

essjj4qmmtrhys4/SFMeetup2013.pdf

Sunday, November 24, 13

Más contenido relacionado

PDF
Ejemplo de RPC (Servidor de Archivos) enviar archivo en Java utilizando RPC
PDF
Creación de aplicaciones web con Node.js y Express
DOCX
PDF
Hacking ético con herramientas Python
RTF
Pila
DOCX
PDF
WPF 09. procesos asíncronos y programación paralela
PDF
Administración de llaves SSH para aplicaciones
Ejemplo de RPC (Servidor de Archivos) enviar archivo en Java utilizando RPC
Creación de aplicaciones web con Node.js y Express
Hacking ético con herramientas Python
Pila
WPF 09. procesos asíncronos y programación paralela
Administración de llaves SSH para aplicaciones

La actualidad más candente (8)

PPTX
Apache Storm: Instalación
PPTX
Apache Storm: Desarrollo
PPTX
Ansible DevOps Day Peru 2016
PPTX
News40 Parallel Computing
KEY
Evadiendo antivirus - uso de crypters
PDF
4... alfabeto de cadenas
PPT
ODP
Taller II Coreis Python 13112009
Apache Storm: Instalación
Apache Storm: Desarrollo
Ansible DevOps Day Peru 2016
News40 Parallel Computing
Evadiendo antivirus - uso de crypters
4... alfabeto de cadenas
Taller II Coreis Python 13112009
Publicidad

Similar a PEP-3156: Async I/O en Python (20)

PDF
Desarrollo aplicaciones distribuidas sockets
PDF
Desarrollando aplicaciones de red con Twisted
PDF
Javier Marcos - Detección de amenazas a escala con osquery [rooted2019]
PPTX
POO Y CONFIGURACION API REST FRAMEWORK DJANGO.pptx
PDF
Scripting para Pentesters v1.0
PPTX
escaneo de puertos.pptx
PDF
Gestión Remota de Equipos con Python
PDF
V2 d2013 jose f irles - freeswitch
PDF
VOIP2DAY 2013: Construyendo una centralita virtual con FreeSWITCH
PPT
Semana 8 api de socket
PDF
Seguridad en Asterisk: Un acercamiento detallado
PPT
Exposicion sistemas seguridad_linux_software_libre
PDF
JVM Reactive Programming
PPTX
19 javascript servidor
PDF
PARADIGMAS FP Y OOP USANDO TÉCNICAS AVANZADAS DE PROGRAMACIÓN ASÍNCRONA
PDF
Curso de VoIP / Parte 04: Conceptos avanzados
PPTX
Sockets/ tcp
PPTX
Sistemas operativos unidad 2
Desarrollo aplicaciones distribuidas sockets
Desarrollando aplicaciones de red con Twisted
Javier Marcos - Detección de amenazas a escala con osquery [rooted2019]
POO Y CONFIGURACION API REST FRAMEWORK DJANGO.pptx
Scripting para Pentesters v1.0
escaneo de puertos.pptx
Gestión Remota de Equipos con Python
V2 d2013 jose f irles - freeswitch
VOIP2DAY 2013: Construyendo una centralita virtual con FreeSWITCH
Semana 8 api de socket
Seguridad en Asterisk: Un acercamiento detallado
Exposicion sistemas seguridad_linux_software_libre
JVM Reactive Programming
19 javascript servidor
PARADIGMAS FP Y OOP USANDO TÉCNICAS AVANZADAS DE PROGRAMACIÓN ASÍNCRONA
Curso de VoIP / Parte 04: Conceptos avanzados
Sockets/ tcp
Sistemas operativos unidad 2
Publicidad

Más de Saúl Ibarra Corretgé (20)

PDF
JanusCon 2024: Mom there are robots in my meeting
PDF
Challenges running Jitsi Meet at scale during the pandemic
PDF
The Road to End-to-End Encryption in Jitsi Meet
PDF
Jitsi: State of the Union 2020
PDF
Jitsi Meet: our tale of blood, sweat, tears and love
PDF
Jitsi Meet: Video conferencing for the privacy minded
PDF
Jitsi - Estado de la unión 2019
PDF
Get a room! Spot: the ultimate physical meeting room experience
PDF
Going Mobile with React Native and WebRTC
PDF
Going Mobile with React Native and WebRTC
PDF
Jitsi: Estado de la Unión (2018)
PDF
Jitsi: state-of-the-art video conferencing you can self-host
PDF
WebRTC: El epicentro de la videoconferencia y IoT
PDF
Jitsi: Open Source Video Conferencing
PDF
Jitsi: State of the Union
PDF
libuv: cross platform asynchronous i/o
PDF
Videoconferencias: el santo grial de WebRTC
PDF
SylkServer: State of the art RTC application server
PDF
Escalabilidad horizontal desde las trincheras
PDF
A deep dive into libuv
JanusCon 2024: Mom there are robots in my meeting
Challenges running Jitsi Meet at scale during the pandemic
The Road to End-to-End Encryption in Jitsi Meet
Jitsi: State of the Union 2020
Jitsi Meet: our tale of blood, sweat, tears and love
Jitsi Meet: Video conferencing for the privacy minded
Jitsi - Estado de la unión 2019
Get a room! Spot: the ultimate physical meeting room experience
Going Mobile with React Native and WebRTC
Going Mobile with React Native and WebRTC
Jitsi: Estado de la Unión (2018)
Jitsi: state-of-the-art video conferencing you can self-host
WebRTC: El epicentro de la videoconferencia y IoT
Jitsi: Open Source Video Conferencing
Jitsi: State of the Union
libuv: cross platform asynchronous i/o
Videoconferencias: el santo grial de WebRTC
SylkServer: State of the art RTC application server
Escalabilidad horizontal desde las trincheras
A deep dive into libuv

Último (20)

PDF
Estrategia de apoyo tecnología grado 9-3
PPTX
Acronis Cyber Protect Cloud para Ciber Proteccion y Ciber Seguridad LATAM - A...
PPTX
RAP01 - TECNICO SISTEMAS TELEINFORMATICOS.pptx
PDF
taller de informática - LEY DE OHM
PPTX
ANCASH-CRITERIOS DE EVALUACIÓN-FORMA-10-10 (2).pptx
PPTX
RAP02 - TECNICO SISTEMAS TELEINFORMATICOS.pptx
PDF
Estrategia de apoyo tecnología miguel angel solis
PDF
Calidad desde el Docente y la mejora continua .pdf
PPT
Que son las redes de computadores y sus partes
PDF
MÓDULO DE CALOR DE GRADO DE MEDIO DE FORMACIÓN PROFESIONAL
PDF
Plantilla para Diseño de Narrativas Transmedia.pdf
PPTX
Propuesta BKP servidores con Acronis1.pptx
PPTX
REDES INFORMATICAS REDES INFORMATICAS.pptx
PPTX
Power Point Nicolás Carrasco (disertación Roblox).pptx
PDF
programa-de-estudios-2011-guc3ada-para-el-maestro-secundarias-tecnicas-tecnol...
PDF
CyberOps Associate - Cisco Networking Academy
PPT
introduccion a las_web en el 2025_mejoras.ppt
PDF
Maste clas de estructura metálica y arquitectura
PDF
Diapositiva proyecto de vida, materia catedra
PDF
clase auditoria informatica 2025.........
Estrategia de apoyo tecnología grado 9-3
Acronis Cyber Protect Cloud para Ciber Proteccion y Ciber Seguridad LATAM - A...
RAP01 - TECNICO SISTEMAS TELEINFORMATICOS.pptx
taller de informática - LEY DE OHM
ANCASH-CRITERIOS DE EVALUACIÓN-FORMA-10-10 (2).pptx
RAP02 - TECNICO SISTEMAS TELEINFORMATICOS.pptx
Estrategia de apoyo tecnología miguel angel solis
Calidad desde el Docente y la mejora continua .pdf
Que son las redes de computadores y sus partes
MÓDULO DE CALOR DE GRADO DE MEDIO DE FORMACIÓN PROFESIONAL
Plantilla para Diseño de Narrativas Transmedia.pdf
Propuesta BKP servidores con Acronis1.pptx
REDES INFORMATICAS REDES INFORMATICAS.pptx
Power Point Nicolás Carrasco (disertación Roblox).pptx
programa-de-estudios-2011-guc3ada-para-el-maestro-secundarias-tecnicas-tecnol...
CyberOps Associate - Cisco Networking Academy
introduccion a las_web en el 2025_mejoras.ppt
Maste clas de estructura metálica y arquitectura
Diapositiva proyecto de vida, materia catedra
clase auditoria informatica 2025.........

PEP-3156: Async I/O en Python

  • 1. PEP-3156 Async I/O en Python Saúl Ibarra Corretgé @saghul PyConES 2013 Sunday, November 24, 13
  • 2. repr(self) >>> from Amsterdam import saghul >>> saghul.work() VoIP, SIP, XMPP, chat, Real Time Communications >>> saghul.other() networking, event loops, sockets, MOAR PYTHON >>> saghul.languages() Python, C >>> saghul.message() Estoy encantado de participar en PyConES! >>> Sunday, November 24, 13
  • 3. import open_source • Core Team de libuv • Tulip / asyncio • Muchos experimentos con event loops y más cosas • Sunday, November 24, 13 github.com/saghul
  • 4. import socket import socket server = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM) server.bind(('127.0.0.1', 1234)) server.listen(128) print("Server listening on: {}".format(server.getsockname())) client, addr = server.accept() print("Client connected: {}".format(addr)) while True: data = client.recv(4096) if not data: print("Client has disconnected") break client.send(data) server.close() Sunday, November 24, 13
  • 5. except Exception • Solo podemos gestionar una conexión • Soluciones para soportar múltiples clientes • Threads • Procesos • Multiplexores de I/O Sunday, November 24, 13
  • 6. import thread import socket import thread def handle_client(client, addr): print("Client connected: {}".format(addr)) while True: data = client.recv(4096) if not data: print("Client has disconnected") break client.send(data) server = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM) server.bind(('127.0.0.1', 1234)) server.listen(128) print("Server listening on: {}".format(server.getsockname())) while True: client, addr = server.accept() thread.start_new_thread(handle_client, (client, addr)) Sunday, November 24, 13
  • 7. except Exception • Los threads añaden overhead • • Tamaño del stack Cambios de contexto • Sincronización entre threads • El GIL - NO es un problema Sunday, November 24, 13
  • 8. Multiplexores de I/O • Examinar y bloquearse a la espera de que un fd esté listo • ¡Aun así la operación puede bloquear! • El fd tiene que ser puesto en modo no bloqueante • ¿Y Windows? Sunday, November 24, 13
  • 10. Multiplexores de I/O 1. Poner un fd en modo no bloqueante 2. Añadir el fd al multiplexor 3. Esperar un rato 4. Realizar la operación bloqueante sobre el fd si está listo Sunday, November 24, 13
  • 11. def set_nonblocking import fcntl def set_nonblocking(fdobj): # unix only try: setblocking = fdobj.setblocking except AttributeError: try: fd = fdobj.fileno() except AttributeError: fd = fdobj flags = fcntl.fcntl(fd, fcntl.F_GETFL) fcntl.fcntl(fd, fcntl.F_SETFL, flags | os.O_NONBLOCK) else: setblocking(False) Sunday, November 24, 13
  • 12. import select • El módulo “select” implementa los distintos multiplexores de i/o • • • • select poll kqueue epoll • En Python 3.4, módulo “selectors” Sunday, November 24, 13
  • 13. sys.platform == ‘win32’ • Soporta select()! • 64 fds por thread • >= Vista soporta WSAPoll! • Está roto: bit.ly/Rg06jX • IOCP es lo que mola Sunday, November 24, 13
  • 14. import IOCP • Empezar la operación de i/o en modo overlapped • Recibe un callback cuando ha terminado • Completion Ports • Abstracción totalmente distinta a Unix Sunday, November 24, 13
  • 15. windows.rules = True Sunday, November 24, 13
  • 17. Frameworks • Los frameworks nos abstraen de las diferentes plataformas • Protocolos • Integracion con otros event loops: Qt, GLib, ... • Distintas APIs Sunday, November 24, 13
  • 18. import twisted • Usa select, poll, kqueue, epoll del módulo select • IOCP en Windows • Integración con otros loops como Qt • Protocolos, transportes, ... • Deferred Sunday, November 24, 13
  • 19. import tornado • Usa select, poll, kqueue, epoll del modulo select • select() en Windows :-( • Principalmente orientado a desarrollo web • API Sunday, November 24, 13 síncrona con coroutines
  • 20. import gevent • Usa libevent en la 0.x y libev en la 1.x • select() en Windows :-( • API síncrona con greenlet Sunday, November 24, 13
  • 21. import asyncore • raise RuntimeError(“NOT GOOD ENOUGH”) • “asyncore: included batteries don’t fit” bit.ly/182HcHT Sunday, November 24, 13
  • 23. I’m not trying to reinvent the wheel. I’m trying to build a good one. Guido van Rossum Sunday, November 24, 13
  • 25. import asyncio • Implementación de referencia del PEP-3156 • Componentes base para i/o asíncrona • Funciona en Python >= 3.3 Sunday, November 24, 13
  • 26. Objetivos • Implementación moderna de i/o asíncrona para Python • Utilizar yield from (PEP-380) • Pero no obligar a nadie • No utilizar nada que requiera Python > 3.3 • Interoprabilidad con otros frameworks Sunday, November 24, 13
  • 27. Objetivos • Soporte para Unix y Windows • IPv4 e IPv6 • TCP, UDP y pipes • SSL básico (seguro por defecto) • Subprocesos Sunday, November 24, 13
  • 28. No Objetivos • Perfección • Reemplazar los frameworks actuales • Implementaciones de protocolos concretos • Reemplazar httplib, smtplib, ... • Funcionar en Python < 3.3 Sunday, November 24, 13
  • 32. Componentes Event loop, policy Coroutines, Futures, Tasks Transports, Protocols Sunday, November 24, 13
  • 34. Event loop y policy • Selecciona el mejor selector para cada plataforma • APIs para crear servidores y conexiones (TCP, UDP, ...) Sunday, November 24, 13
  • 35. Callbacks • loop.call_soon(func, *args) • loop.call_later(delay, func, *args) • loop.call_at(when, func, *args) • loop.time() Sunday, November 24, 13
  • 36. Callbacks para I/O • loop.add_reader(fd, func, *args) • loop.add_writer(fd, func, *args) • loop.remove_reader(fd) • loop.remove_writer(fd) Sunday, November 24, 13
  • 37. Señales Unix • loop.add_signal_handler(sig, func, *args) • loop.remove_signal_handler(sig) Sunday, November 24, 13
  • 38. Interfaz con Threads • loop.call_soon_threadsafe(func, *args) • loop.run_in_executor(exc, func, *args) • loop.set_default_executor(exc) Sunday, November 24, 13
  • 39. Inicio y parada • loop.run_forever() • loop.stop() • loop.run_until_complete(f) Sunday, November 24, 13
  • 40. Acceso a la instancia • get_event_loop() • set_event_loop(loop) • new_event_loop() Sunday, November 24, 13
  • 41. Policy (default) • Un event loop por thread • Solo se crea un loop automágicamente para el main thread Sunday, November 24, 13
  • 42. Policy • Configura qué hacen get/set/new _event_loop • Es el único objeto global • ¡Se puede cambiar! (ejemplo: rose) Sunday, November 24, 13
  • 44. Coroutines, Futures y Tasks • Coroutines • • una función generator, puede recibir valores • promesa de resultado o error • Future que ejecuta una coroutine decorada con @coroutine • Future • Task Sunday, November 24, 13
  • 45. Coroutines y yield from import asyncio import socket loop = asyncio.get_event_loop() @asyncio.coroutine def handle_client(client, addr): print("Client connected: {}".format(addr)) while True: data = yield from loop.sock_recv(client, 4096) if not data: print("Client has disconnected") break client.send(data) @asyncio.coroutine def accept_connections(server_socket): while True: client, addr = yield from loop.sock_accept(server_socket) asyncio.async(handle_client(client, addr)) server = socket.socket(family=socket.AF_INET, type=socket.SOCK_STREAM) server.bind(('127.0.0.1', 1234)) server.listen(128) server.setblocking(False) print("Server listening on: {}".format(server.getsockname())) loop.run_until_complete(accept_connections(server)) Sunday, November 24, 13
  • 46. Coroutines y yield from • Imagina que el yield from no existe • Imagina que el código es secuencial • No te bases en la definición formal de yield from (PEP-380) Sunday, November 24, 13
  • 47. Futures • Parecidos a los Futures de PEP-3148 • concurrent.futures.Future • • • • • f.set_result(); r = f.result() • API (casi) idéntico: Sunday, November 24, 13 f.set_exception(e); e = f.exception() f.done() f.add_done_callback(x); f.remove_done_callback(x) f.cancel(); f.cancelled()
  • 48. Futures + Coroutines • yield from funciona con los Futures! • • f = Future() • Alguien pondrá el resultado o la excepción luego r = yield from f • Espera a que esté listo y devuelve f.result() • Normalmente devueltos por funciones Sunday, November 24, 13
  • 49. Deshaciendo callbacks @asyncio.coroutine def sync_looking_function(*args): fut = asyncio.Future() def cb(result, error): if error is not None: fut.set_result(result) else: fut.set_exception(Exception(error)) async_function(cb, *args) return (yield from fut) Sunday, November 24, 13
  • 50. Tasks • Unicornios con polvo de hada • Es una coroutine metida en un Future • WAT • Hereda de Future • Funciona con yield from • Sunday, November 24, 13 r = yield from Task(coro(...))
  • 51. Tasks vs coroutines • Una coroutine no “avanza” sin un mechanismo de scheduling • Los Tasks pueden avanzar solos, sin necesidad de esperar • El event loop es el scheduler! • Sunday, November 24, 13 Magia!
  • 52. Otro ejemplo import asyncio loop = asyncio.get_event_loop() clients = {} # task -> (reader, writer) def _accept_client(client_reader, client_writer): task = asyncio.Task(_handle_client(client_reader, client_writer)) clients[task] = (client_reader, client_writer) def client_done(task): del clients[task] task.add_done_callback(client_done) @asyncio.coroutine def _handle_client(client_reader, client_writer): while True: data = (yield from client_reader.readline()) client_writer.write(data) f = asyncio.start_server(_accept_client, '127.0.0.1', 12345) server = loop.run_until_complete(f) loop.run_forever() Sunday, November 24, 13
  • 54. Transports y Protocols • Transport: representa una conexión (socket, pipe, ...) • Protocol: representa una aplicación (servidor HTTP, cliente IRC, ...) • Siempre van juntos • API basada en llamadas a función y callbacks Sunday, November 24, 13
  • 55. Clientes y servidores • loop.create_connection(...) • crea un Transport y un Protocol • crea un Transport y un Protocol por cada conexión aceptada • devuelve un objeto Server • loop.create_server(...) Sunday, November 24, 13
  • 56. Clientes y servidores • loop.open_connection(...) • wrapper sobre create_connection, devuelve (stream_reader, stream_writer) • loop.start_server(...) • Sunday, November 24, 13 wrapper sobre create_server, ejecuta un callback con (stream_reader, stream_writer) por cada conexión aceptada
  • 57. Interfaz Transport -> Protocol • connection_made(transport) • data_received(data) • eof_received() • connection_lost(exc) Sunday, November 24, 13
  • 58. Interfaz Protocol -> Transport • write(data) • writelines(seq) • write_eof() • close() • abort() Sunday, November 24, 13
  • 59. MOAR PROTOCOL! • ¡Esta tarde a las 17:30! • “Tulip or not Tulip” - Iñaki Galarza Sunday, November 24, 13
  • 60. ¿Y ahora qué? • Ven a la charla de Iñaki • Lee el PEP-3156 • Implementa algún protocolo sencillo (cliente IRC por ejemplo) • ¡Usa asyncio en tu próximo proyecto! Sunday, November 24, 13
  • 62. Referencias • code.google.com/p/tulip/ • groups.google.com/forum/#!forum/ python-tulip • PEP-3156 • http://www.youtube.com/watch? v=1coLC-MUCJc • https://www.dropbox.com/s/ essjj4qmmtrhys4/SFMeetup2013.pdf Sunday, November 24, 13