SlideShare una empresa de Scribd logo
1 de 62
Descargar para leer sin conexión
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

La actualidad más candente (8)

Apache Storm: Instalación
Apache Storm: InstalaciónApache Storm: Instalación
Apache Storm: Instalación
 
Apache Storm: Desarrollo
Apache Storm: DesarrolloApache Storm: Desarrollo
Apache Storm: Desarrollo
 
Ansible DevOps Day Peru 2016
Ansible DevOps Day Peru 2016Ansible DevOps Day Peru 2016
Ansible DevOps Day Peru 2016
 
News40 Parallel Computing
News40 Parallel ComputingNews40 Parallel Computing
News40 Parallel Computing
 
Evadiendo antivirus - uso de crypters
Evadiendo antivirus - uso de cryptersEvadiendo antivirus - uso de crypters
Evadiendo antivirus - uso de crypters
 
4... alfabeto de cadenas
4... alfabeto de cadenas4... alfabeto de cadenas
4... alfabeto de cadenas
 
Procesos
ProcesosProcesos
Procesos
 
Taller II Coreis Python 13112009
Taller II Coreis Python 13112009Taller II Coreis Python 13112009
Taller II Coreis Python 13112009
 

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

Desarrollo aplicaciones distribuidas sockets
Desarrollo aplicaciones distribuidas socketsDesarrollo aplicaciones distribuidas sockets
Desarrollo aplicaciones distribuidas sockets
dandark2000
 
Desarrollando aplicaciones de red con Twisted
Desarrollando aplicaciones de red con TwistedDesarrollando aplicaciones de red con Twisted
Desarrollando aplicaciones de red con Twisted
jjconti
 
Scripting para Pentesters v1.0
Scripting para Pentesters v1.0Scripting para Pentesters v1.0
Scripting para Pentesters v1.0
wcuestas
 
V2 d2013 jose f irles - freeswitch
V2 d2013   jose f irles - freeswitchV2 d2013   jose f irles - freeswitch
V2 d2013 jose f irles - freeswitch
VOIP2DAY
 
Sistemas operativos unidad 2
Sistemas operativos unidad 2Sistemas operativos unidad 2
Sistemas operativos unidad 2
Luis Cigarroa
 
Escaneo de puertos clase 2 complemento b 28 02-13
Escaneo de puertos clase 2 complemento b 28 02-13Escaneo de puertos clase 2 complemento b 28 02-13
Escaneo de puertos clase 2 complemento b 28 02-13
Tensor
 

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

Desarrollo aplicaciones distribuidas sockets
Desarrollo aplicaciones distribuidas socketsDesarrollo aplicaciones distribuidas sockets
Desarrollo aplicaciones distribuidas sockets
 
Desarrollando aplicaciones de red con Twisted
Desarrollando aplicaciones de red con TwistedDesarrollando aplicaciones de red con Twisted
Desarrollando aplicaciones de red con Twisted
 
Javier Marcos - Detección de amenazas a escala con osquery [rooted2019]
Javier Marcos - Detección de amenazas a escala con osquery [rooted2019]Javier Marcos - Detección de amenazas a escala con osquery [rooted2019]
Javier Marcos - Detección de amenazas a escala con osquery [rooted2019]
 
Scripting para Pentesters v1.0
Scripting para Pentesters v1.0Scripting para Pentesters v1.0
Scripting para Pentesters v1.0
 
M18
M18M18
M18
 
escaneo de puertos.pptx
escaneo de puertos.pptxescaneo de puertos.pptx
escaneo de puertos.pptx
 
Gestión Remota de Equipos con Python
Gestión Remota de Equipos con PythonGestión Remota de Equipos con Python
Gestión Remota de Equipos con Python
 
V2 d2013 jose f irles - freeswitch
V2 d2013   jose f irles - freeswitchV2 d2013   jose f irles - freeswitch
V2 d2013 jose f irles - freeswitch
 
VOIP2DAY 2013: Construyendo una centralita virtual con FreeSWITCH
VOIP2DAY 2013: Construyendo una centralita virtual con FreeSWITCHVOIP2DAY 2013: Construyendo una centralita virtual con FreeSWITCH
VOIP2DAY 2013: Construyendo una centralita virtual con FreeSWITCH
 
Semana 8 api de socket
Semana  8 api de socketSemana  8 api de socket
Semana 8 api de socket
 
Seguridad en Asterisk: Un acercamiento detallado
Seguridad en Asterisk: Un acercamiento detalladoSeguridad en Asterisk: Un acercamiento detallado
Seguridad en Asterisk: Un acercamiento detallado
 
Exposicion sistemas seguridad_linux_software_libre
Exposicion sistemas seguridad_linux_software_libreExposicion sistemas seguridad_linux_software_libre
Exposicion sistemas seguridad_linux_software_libre
 
Zookeeper
ZookeeperZookeeper
Zookeeper
 
JVM Reactive Programming
JVM Reactive ProgrammingJVM Reactive Programming
JVM Reactive Programming
 
19 javascript servidor
19 javascript servidor19 javascript servidor
19 javascript servidor
 
PARADIGMAS FP Y OOP USANDO TÉCNICAS AVANZADAS DE PROGRAMACIÓN ASÍNCRONA
PARADIGMAS FP  Y OOP USANDO TÉCNICAS AVANZADAS DE PROGRAMACIÓN ASÍNCRONAPARADIGMAS FP  Y OOP USANDO TÉCNICAS AVANZADAS DE PROGRAMACIÓN ASÍNCRONA
PARADIGMAS FP Y OOP USANDO TÉCNICAS AVANZADAS DE PROGRAMACIÓN ASÍNCRONA
 
Curso de VoIP / Parte 04: Conceptos avanzados
Curso de VoIP / Parte 04: Conceptos avanzadosCurso de VoIP / Parte 04: Conceptos avanzados
Curso de VoIP / Parte 04: Conceptos avanzados
 
Sockets/ tcp
Sockets/ tcpSockets/ tcp
Sockets/ tcp
 
Sistemas operativos unidad 2
Sistemas operativos unidad 2Sistemas operativos unidad 2
Sistemas operativos unidad 2
 
Escaneo de puertos clase 2 complemento b 28 02-13
Escaneo de puertos clase 2 complemento b 28 02-13Escaneo de puertos clase 2 complemento b 28 02-13
Escaneo de puertos clase 2 complemento b 28 02-13
 

Más de Saúl Ibarra Corretgé

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

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

Último

redes informaticas en una oficina administrativa
redes informaticas en una oficina administrativaredes informaticas en una oficina administrativa
redes informaticas en una oficina administrativa
nicho110
 

Último (12)

pruebas unitarias unitarias en java con JUNIT
pruebas unitarias unitarias en java con JUNITpruebas unitarias unitarias en java con JUNIT
pruebas unitarias unitarias en java con JUNIT
 
Avances tecnológicos del siglo XXI 10-07 eyvana
Avances tecnológicos del siglo XXI 10-07 eyvanaAvances tecnológicos del siglo XXI 10-07 eyvana
Avances tecnológicos del siglo XXI 10-07 eyvana
 
Avances tecnológicos del siglo XXI y ejemplos de estos
Avances tecnológicos del siglo XXI y ejemplos de estosAvances tecnológicos del siglo XXI y ejemplos de estos
Avances tecnológicos del siglo XXI y ejemplos de estos
 
redes informaticas en una oficina administrativa
redes informaticas en una oficina administrativaredes informaticas en una oficina administrativa
redes informaticas en una oficina administrativa
 
investigación de los Avances tecnológicos del siglo XXI
investigación de los Avances tecnológicos del siglo XXIinvestigación de los Avances tecnológicos del siglo XXI
investigación de los Avances tecnológicos del siglo XXI
 
EVOLUCION DE LA TECNOLOGIA Y SUS ASPECTOSpptx
EVOLUCION DE LA TECNOLOGIA Y SUS ASPECTOSpptxEVOLUCION DE LA TECNOLOGIA Y SUS ASPECTOSpptx
EVOLUCION DE LA TECNOLOGIA Y SUS ASPECTOSpptx
 
Resistencia extrema al cobre por un consorcio bacteriano conformado por Sulfo...
Resistencia extrema al cobre por un consorcio bacteriano conformado por Sulfo...Resistencia extrema al cobre por un consorcio bacteriano conformado por Sulfo...
Resistencia extrema al cobre por un consorcio bacteriano conformado por Sulfo...
 
PROYECTO FINAL. Tutorial para publicar en SlideShare.pptx
PROYECTO FINAL. Tutorial para publicar en SlideShare.pptxPROYECTO FINAL. Tutorial para publicar en SlideShare.pptx
PROYECTO FINAL. Tutorial para publicar en SlideShare.pptx
 
EL CICLO PRÁCTICO DE UN MOTOR DE CUATRO TIEMPOS.pptx
EL CICLO PRÁCTICO DE UN MOTOR DE CUATRO TIEMPOS.pptxEL CICLO PRÁCTICO DE UN MOTOR DE CUATRO TIEMPOS.pptx
EL CICLO PRÁCTICO DE UN MOTOR DE CUATRO TIEMPOS.pptx
 
How to use Redis with MuleSoft. A quick start presentation.
How to use Redis with MuleSoft. A quick start presentation.How to use Redis with MuleSoft. A quick start presentation.
How to use Redis with MuleSoft. A quick start presentation.
 
Innovaciones tecnologicas en el siglo 21
Innovaciones tecnologicas en el siglo 21Innovaciones tecnologicas en el siglo 21
Innovaciones tecnologicas en el siglo 21
 
Buenos_Aires_Meetup_Redis_20240430_.pptx
Buenos_Aires_Meetup_Redis_20240430_.pptxBuenos_Aires_Meetup_Redis_20240430_.pptx
Buenos_Aires_Meetup_Redis_20240430_.pptx
 

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