SlideShare a Scribd company logo
1 of 81
Download to read offline
Python
Asíncrono
¿echas de menos las
promesas?
@javierabadia
DISCLAIMER
pero…
Javier Abadía
VP of Engineering @ StyleSage
tuplas, listas, etc
comprensiones
librerías para todo
claves de diccionarios
funciones anónimas
asincronía
❤
const API_URL = `https://api.openweathermap.org/data/2.5/weather?appid=${API_KEY}&units=metric`;
// list of cities
const CITIES = [
'London', 'Tokyo', 'Melbourne', 'Vancouver',
'Lagos', 'Berlin', 'Paris', 'Johannesburg',
'Chicago', 'Mumbai', 'Cairo', 'Beijing'
];
const fetchTemperatureForCity = city => {
// For example: ['Lagos', 29.28]
return fetch(`${API_URL}&q=${encodeURIComponent(city)}`)
.then(response => response.json())
.then(data => [ city, data.main.temp || null ]);
}
const fetchTemperatureForCities = cities => {
return Promise.all(cities.map(fetchTemperatureForCity))
.then(temps => {
return temps.reduce((data, [ city, temp ]) => {
return { ...data, [city]: Number.isFinite(temp) ? temp.toFixed(2) * 1 : null };
}, {});
});
}
fetchTemperatureForCities(CITIES)
.then(console.log, console.error);
si tuviera que
hacer esto en una
vista de Django…
…no sabría
Si Python fuera un bar…
BAR
BAR
Una Hamburguesa,
con patatas grandes
y una cerveza,
por favor Enseguida!
esperar esperar servir la cerveza
pedir la hamburguesa
a la cocina
poner las patatatas
a freir
sacar las patatas
de la freidora
1 cliente = 10 min
BAR
esperar
poner las
patatatas a freir
pedir la
hamburguesa a la
cocina
esperar servir la cerveza
sacar las patatas
de la freidora
esperar
poner las
patatatas a freir
pedir la
hamburguesa a la
cocina
esperar servir la cerveza
sacar las patatas
de la freidora
esperar
poner las
patatatas a freir
pedir la
hamburguesa a la
cocina
esperar servir la cerveza
sacar las patatas
de la freidora
3 clientes (10, 20, 30) ⋍ 20 min
atender más
clientes a la vez
esperar
poner las
patatatas a freir
pedir la
hamburguesa a la
cocina
esperar servir la cerveza
sacar las patatas
de la freidora
esperar
poner las
patatatas a freir
pedir la
hamburguesa a la
cocina
esperar servir la cerveza
sacar las patatas
de la freidora
esperar
poner las
patatatas a freir
pedir la
hamburguesa a la
cocina
esperar servir la cerveza
sacar las patatas
de la freidora
atender a un cliente
en menos tiempo
hacer un mejor
uso de los recursos
https://gist.github.com/hellerbarde/2843375
Tiempos
System Event Actual Latency Scaled Latency
One CPU cycle 0.4 ns 1 s
Level 1 cache access 0.9 ns 2 s
Level 2 cache access 2.8 ns 7 s
Level 3 cache access 28 ns 1 min
Main memory access (DDR DIMM) ~100 ns 4 min
NVMe SSD I/O ~25 μs 17 hrs
SSD I/O 50–150 μs 1.5 - 4 days
Rotational disk I/O 1–10 ms 1-9 months
Internet call: San Francisco to New York
City
65 ms 5 years
Internet call: San Francisco to Hong Kong 141 ms 11 years
url = 'http://example.com/david-hasselhoff.jpg'
path = 'media/cool-pics/screen-background.jpg’
r = requests.get(url, stream=True)
if r.status_code == 200:
with open(path, 'wb') as f:
for chunk in r.iter_content(1024):
f.write(chunk)
im = Image.open(path)
im.thumbnail(size, Image.ANTIALIAS)
im.save(thumbnail_path, "JPEG")
pic = CoolPics(img=path, thumbnail=thumbnail_path)
pic.save()
varios años
varios meses
varios meses
varios meses
varios meses
unas pocas horas
varios meses
< de una hora
varios meses
url = 'http://example.com/david-hasselhoff.jpg'
path = 'media/cool-pics/screen-background.jpg’
r = requests.get(url, stream=True)
if r.status_code == 200:
with open(path, 'wb') as f:
for chunk in r.iter_content(1024):
f.write(chunk)
im = Image.open(path)
im.thumbnail(size, Image.ANTIALIAS)
im.save(thumbnail_path, "JPEG")
pic = CoolPics(img=path, thumbnail=thumbnail_path)
pic.save()
varios años
varios meses
varios meses
varios meses
varios meses
unas pocas horas
varios meses
< de una hora
varios meses
naturalezasecuencial
x 2000
¿qué podemos hacer?
BAR
esperar
poner las
patatatas a freir
pedir la
hamburguesa a la
cocina
esperar servir la cerveza
sacar las patatas
de la freidora
esperar
poner las
patatatas a freir
pedir la
hamburguesa a la
cocina
esperar servir la cerveza
sacar las patatas
de la freidora
esperar
poner las
patatatas a freir
pedir la
hamburguesa a la
cocina
esperar servir la cerveza
sacar las patatas
de la freidora
3 clientes (10, 12, 20) ⋍ 14 min
import threading
import time
class MyThread(threading.Thread):
def __init__(self, thread_id, name, delay):
super().__init__()
self.thread_id = thread_id
self.name = name
self.delay = delay
def run(self):
print("Starting " + self.name)
# Get lock to synchronize threads
# g_thread_lock.acquire()
print_time(self.name, 3, self.delay)
# Free lock to release next thread
# g_thread_lock.release()
def print_time(thread_name, counter, delay):
while counter:
time.sleep(delay)
print("%s: %s" % (
thread_name,
time.ctime(time.time()))
)
counter -= 1
# …
# …
g_thread_lock = threading.Lock()
threads = []
# Create new threads
thread1 = MyThread(1, "Thread-1", 1)
thread2 = MyThread(2, "Thread-2", 2)
# Start new Threads
thread1.start()
thread2.start()
# Add threads to thread list
threads.append(thread1)
threads.append(thread2)
# Wait for all threads to complete
for t in threads:
t.join()
print("Exiting Main Thread")
threading
import threading
import time
class MyThread(threading.Thread):
def __init__(self, thread_id, name, delay):
super().__init__()
self.thread_id = thread_id
self.name = name
self.delay = delay
def run(self):
print("Starting " + self.name)
# Get lock to synchronize threads
# g_thread_lock.acquire()
print_time(self.name, 3, self.delay)
# Free lock to release next thread
# g_thread_lock.release()
def print_time(thread_name, counter, delay):
while counter:
time.sleep(delay)
print("%s: %s" % (
thread_name,
time.ctime(time.time()))
)
counter -= 1
# …
# …
g_thread_lock = threading.Lock()
threads = []
# Create new threads
thread1 = MyThread(1, "Thread-1", 1)
thread2 = MyThread(2, "Thread-2", 2)
# Start new Threads
thread1.start()
thread2.start()
# Add threads to thread list
threads.append(thread1)
threads.append(thread2)
# Wait for all threads to complete
for t in threads:
t.join()
print("Exiting Main Thread")
crear las threads
import threading
import time
class MyThread(threading.Thread):
def __init__(self, thread_id, name, delay):
super().__init__()
self.thread_id = thread_id
self.name = name
self.delay = delay
def run(self):
print("Starting " + self.name)
# Get lock to synchronize threads
# g_thread_lock.acquire()
print_time(self.name, 3, self.delay)
# Free lock to release next thread
# g_thread_lock.release()
def print_time(thread_name, counter, delay):
while counter:
time.sleep(delay)
print("%s: %s" % (
thread_name,
time.ctime(time.time()))
)
counter -= 1
# …
# …
g_thread_lock = threading.Lock()
threads = []
# Create new threads
thread1 = MyThread(1, "Thread-1", 1)
thread2 = MyThread(2, "Thread-2", 2)
# Start new Threads
thread1.start()
thread2.start()
# Add threads to thread list
threads.append(thread1)
threads.append(thread2)
# Wait for all threads to complete
for t in threads:
t.join()
print("Exiting Main Thread")
arrancarlas
import threading
import time
class MyThread(threading.Thread):
def __init__(self, thread_id, name, delay):
super().__init__()
self.thread_id = thread_id
self.name = name
self.delay = delay
def run(self):
print("Starting " + self.name)
# Get lock to synchronize threads
# g_thread_lock.acquire()
print_time(self.name, 3, self.delay)
# Free lock to release next thread
# g_thread_lock.release()
def print_time(thread_name, counter, delay):
while counter:
time.sleep(delay)
print("%s: %s" % (
thread_name,
time.ctime(time.time()))
)
counter -= 1
# …
# …
g_thread_lock = threading.Lock()
threads = []
# Create new threads
thread1 = MyThread(1, "Thread-1", 1)
thread2 = MyThread(2, "Thread-2", 2)
# Start new Threads
thread1.start()
thread2.start()
# Add threads to thread list
threads.append(thread1)
threads.append(thread2)
# Wait for all threads to complete
for t in threads:
t.join()
print("Exiting Main Thread")
¿sincronizarlas?
import threading
import time
class MyThread(threading.Thread):
def __init__(self, thread_id, name, delay):
super().__init__()
self.thread_id = thread_id
self.name = name
self.delay = delay
def run(self):
print("Starting " + self.name)
# Get lock to synchronize threads
# g_thread_lock.acquire()
print_time(self.name, 3, self.delay)
# Free lock to release next thread
# g_thread_lock.release()
def print_time(thread_name, counter, delay):
while counter:
time.sleep(delay)
print("%s: %s" % (
thread_name,
time.ctime(time.time()))
)
counter -= 1
# …
# …
g_thread_lock = threading.Lock()
threads = []
# Create new threads
thread1 = MyThread(1, "Thread-1", 1)
thread2 = MyThread(2, "Thread-2", 2)
# Start new Threads
thread1.start()
thread2.start()
# Add threads to thread list
threads.append(thread1)
threads.append(thread2)
# Wait for all threads to complete
for t in threads:
t.join()
print("Exiting Main Thread")
esperar a que terminen
thread safety
hcp://edot.org/pyfaq/what-kinds-of-global-value-mutafon-are-thread-safe.htm
songs = []
songs.append(my_song)
songs.pop()
songs.sort()
artist_ages.keys()
i = i+1
songs[i] = songs[j]
if songs:
song = songs.pop()
artist_ages[‘Bob’] += 1
hay mejores
formas de
usar threads
BAR BAR
BAR BAR
BAR BAR
esperar
poner las
patatatas a freir
pedir la
hamburguesa a la
cocina
esperar servir la cerveza
sacar las patatas
de la freidora
esperar
poner las
patatatas a freir
pedir la
hamburguesa a la
cocina
esperar servir la cerveza
sacar las patatas
de la freidora
esperar
poner las
patatatas a freir
pedir la
hamburguesa a la
cocina
esperar servir la cerveza
sacar las patatas
de la freidora
3 clientes (10, 10, 20) ⋍ 13.3 min
from multiprocessing import Lock, Process,
Queue, current_process
import time
import queue # imported for using queue.Empty exception
def do_job(tasks_to_accomplish, tasks_that_are_done):
while True:
try:
task = tasks_to_accomplish.get_nowait()
except queue.Empty:
break
else:
print(task)
tasks_that_are_done.put(task +
' is done by ' + current_process().name)
time.sleep(.5)
return True
def main():
number_of_task = 10
number_of_processes = 4
tasks_to_accomplish = Queue()
tasks_that_are_done = Queue()
processes = []
for i in range(number_of_task):
tasks_to_accomplish.put("Task no " + str(i))
# creating processes
for w in range(number_of_processes):
p = Process(
target=do_job,
args=(tasks_to_accomplish, tasks_that_are_done)
)
processes.append(p)
p.start()
# completing process
for p in processes:
p.join()
# print the output
while not tasks_that_are_done.empty():
print(tasks_that_are_done.get())
return True
if __name__ == '__main__':
main()
mulf-processing
from multiprocessing import Lock, Process,
Queue, current_process
import time
import queue # imported for using queue.Empty exception
def do_job(tasks_to_accomplish, tasks_that_are_done):
while True:
try:
task = tasks_to_accomplish.get_nowait()
except queue.Empty:
break
else:
print(task)
tasks_that_are_done.put(task +
' is done by ' + current_process().name)
time.sleep(.5)
return True
def main():
number_of_task = 10
number_of_processes = 4
tasks_to_accomplish = Queue()
tasks_that_are_done = Queue()
processes = []
for i in range(number_of_task):
tasks_to_accomplish.put("Task no " + str(i))
# creating processes
for w in range(number_of_processes):
p = Process(
target=do_job,
args=(tasks_to_accomplish, tasks_that_are_done)
)
processes.append(p)
p.start()
# completing process
for p in processes:
p.join()
# print the output
while not tasks_that_are_done.empty():
print(tasks_that_are_done.get())
return True
if __name__ == '__main__':
main()
multi-processing
from multiprocessing import Lock, Process,
Queue, current_process
import time
import queue # imported for using queue.Empty exception
def do_job(tasks_to_accomplish, tasks_that_are_done):
while True:
try:
task = tasks_to_accomplish.get_nowait()
except queue.Empty:
break
else:
print(task)
tasks_that_are_done.put(task +
' is done by ' + current_process().name)
time.sleep(.5)
return True
def main():
number_of_task = 10
number_of_processes = 4
tasks_to_accomplish = Queue()
tasks_that_are_done = Queue()
processes = []
for i in range(number_of_task):
tasks_to_accomplish.put("Task no " + str(i))
# creating processes
for w in range(number_of_processes):
p = Process(
target=do_job,
args=(tasks_to_accomplish, tasks_that_are_done)
)
processes.append(p)
p.start()
# completing process
for p in processes:
p.join()
# print the output
while not tasks_that_are_done.empty():
print(tasks_that_are_done.get())
return True
if __name__ == '__main__':
main()
multi-processing
crear colas IPC
from multiprocessing import Lock, Process,
Queue, current_process
import time
import queue # imported for using queue.Empty exception
def do_job(tasks_to_accomplish, tasks_that_are_done):
while True:
try:
task = tasks_to_accomplish.get_nowait()
except queue.Empty:
break
else:
print(task)
tasks_that_are_done.put(task +
' is done by ' + current_process().name)
time.sleep(.5)
return True
def main():
number_of_task = 10
number_of_processes = 4
tasks_to_accomplish = Queue()
tasks_that_are_done = Queue()
processes = []
for i in range(number_of_task):
tasks_to_accomplish.put("Task no " + str(i))
# creating processes
for w in range(number_of_processes):
p = Process(
target=do_job,
args=(tasks_to_accomplish, tasks_that_are_done)
)
processes.append(p)
p.start()
# completing process
for p in processes:
p.join()
# print the output
while not tasks_that_are_done.empty():
print(tasks_that_are_done.get())
return True
if __name__ == '__main__':
main()
multi-processing
crear los procesos
from multiprocessing import Lock, Process,
Queue, current_process
import time
import queue # imported for using queue.Empty exception
def do_job(tasks_to_accomplish, tasks_that_are_done):
while True:
try:
task = tasks_to_accomplish.get_nowait()
except queue.Empty:
break
else:
print(task)
tasks_that_are_done.put(task +
' is done by ' + current_process().name)
time.sleep(.5)
return True
def main():
number_of_task = 10
number_of_processes = 4
tasks_to_accomplish = Queue()
tasks_that_are_done = Queue()
processes = []
for i in range(number_of_task):
tasks_to_accomplish.put("Task no " + str(i))
# creating processes
for w in range(number_of_processes):
p = Process(
target=do_job,
args=(tasks_to_accomplish, tasks_that_are_done)
)
processes.append(p)
p.start()
# completing process
for p in processes:
p.join()
# print the output
while not tasks_that_are_done.empty():
print(tasks_that_are_done.get())
return True
if __name__ == '__main__':
main()
multi-processing
ejecutar los procesos
from multiprocessing import Lock, Process,
Queue, current_process
import time
import queue # imported for using queue.Empty exception
def do_job(tasks_to_accomplish, tasks_that_are_done):
while True:
try:
task = tasks_to_accomplish.get_nowait()
except queue.Empty:
break
else:
print(task)
tasks_that_are_done.put(task +
' is done by ' + current_process().name)
time.sleep(.5)
return True
def main():
number_of_task = 10
number_of_processes = 4
tasks_to_accomplish = Queue()
tasks_that_are_done = Queue()
processes = []
for i in range(number_of_task):
tasks_to_accomplish.put("Task no " + str(i))
# creating processes
for w in range(number_of_processes):
p = Process(
target=do_job,
args=(tasks_to_accomplish, tasks_that_are_done)
)
processes.append(p)
p.start()
# completing process
for p in processes:
p.join()
# print the output
while not tasks_that_are_done.empty():
print(tasks_that_are_done.get())
return True
if __name__ == '__main__':
main()
multi-processing
esperar a que
terminen todos
I/O bound CPU bound
multi-
threading
mulf-
processing
comparten
memoria
GIL
más pesados
no comparten
memoria
IPC
Global Interpreter Lock
• El intérprete de Python no es thread-safe
• Específico de ALGUNAS implementaciones de Python (CPython, PyPy)
• Solo una thread puede estar interpretando código Python en un
proceso
• El intérprete “suelta” el “lock” para operaciones I/O (o incluso NumPy)
• Consecuencias:
• tareas limitadas por I/O van más rápido con múltiples threads
• tareas limitadas por CPU van más lento con múltiples threads
más rápido
¡más lento!
(por culpa del GIL)
más rápido
(pero más ”caro”)
más rápido
I/O bound CPU bound
multi-
threading
multi-
processing
comparten
memoria
GIL
más pesados
no comparten
memoria
IPC
pero… ¿cómo lo hace JavaScript?
BAR
servir la cerveza
pedir la hamburguesa a la
cocina
poner las patatatas a
freir
sacar las patatas de
la freidora
servir la cerveza
pedir la hamburguesa a la
cocina
poner las patatatas a
freir
sacar las patatas de
la freidora
servir la cerveza
pedir la hamburguesa a la
cocina
poner las patatatas a
freir
sacar las patatas de
la freidora
3 clientes (4,5,7) ⋍ 5,33 min
Modelo de Concurrencia de JavaScript
• en JavaScript solo hay una thread de usuario
• el código se ejecuta “por turnos”, sin ninguna interrupción, siempre hasta
el final
• dentro de un “bucle de eventos”
• TODAS las operaciones de I/O son asíncronas:
• se lanzan en el momento
• el código no espera a que se termine la ejecución
• el resultado se recibe en un callback (o una Promesa) que se ejecutará en un turno
en el futuro
• También son asíncronas todas las funciones que llaman a una función
asíncrona
https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop
TURNO 1 TURNO 2
event loopevent loopevent loopevent loop
TURNO 1 TURNO 2
Python asyncio - async/await
Python 3.4+
# https://docs.python.org/3/library/asyncio-task.html
import asyncio
import time
async def say_after(delay, what):
await asyncio.sleep(delay)
print(what)
async def main():
print(f"started at {time.strftime('%X')}")
await say_after(1, 'hello')
await say_after(2, 'world')
print(f"finished at {time.strftime('%X')}")
asyncio.run(main())
bucle de eventos
await ≈ yield
import asyncio
import time
async def say_after(delay, what):
await asyncio.sleep(delay)
print(what)
async def main():
print(f"started at {time.strftime('%X')}")
t1 = say_after(1, 'hello')
t2 = say_after(2, 'world')
await asyncio.gather(t1, t2)
print(f"finished at {time.strftime('%X')}")
asyncio.run(main())
concurrencia cooperativa
¡por fin!
¿no?
si no hay cooperación, no funciona
• en JavaScript la cooperación es
obligatoria
• todas las librerías son asíncronas
• en Python casi todas las librerías
son síncronas (no cooperan)
nuestro código no debe bloquearse
debe devolver el control al bucle de eventos
no hay un “scheduler pre-emptivo”
el problema es…
• todo lo que NO podemos usar
• http, requests
• acceso a bases de datos
• I/O de ficheros
• necesitamos nuevas librerías para todo
• aiohttp
• aiopg
• aiomysql
• aiofiles
• https://github.com/timofurrer/awesome-asyncio
SYNC ASYNC
es difícil
• converfr un proyecto existente en async
• o una parte
• en un nuevo proyecto async
• encontrar y usar librerías
• p.ej script que se conecta a nuestra cuenta de GitHub y crea un informe de
branches en Excel
• pygithub - hace llamadas de red
• openpyxl - lee y escribe ficheros
¿entonces?
concurrent.futures
• librería de alto nivel
• usando multi-processing o multi-threading con la misma interfaz
• proporciona una sintaxis parecida a las promesas
• compatible con todas las librerías síncronas
• si son thread-safe podemos usar multi-threading
• si no, tendremos que usar multi-processing
Python 3.22011-02-20
import threading
from concurrent import futures
from random import random
from time import sleep
import requests
nums = range(1, 11)
url_tpl = "http://jsonplaceholder.typicode.com/todos/{}"
def get_data(myid):
url = url_tpl.format(myid)
data = requests.get(url).json()
sleep(random() * 5)
return data
def main():
with futures.ThreadPoolExecutor(4) as executor:
results = executor.map(get_data, nums)
print()
for result in results:
print(result)
if __name__ == '__main__':
main()
futures
import threading
from concurrent import futures
from random import random
from time import sleep
import requests
nums = range(1, 11)
url_tpl = "http://jsonplaceholder.typicode.com/todos/{}"
def get_data(myid):
url = url_tpl.format(myid)
data = requests.get(url).json()
sleep(random() * 5)
return data
def main():
with futures.ThreadPoolExecutor(4) as executor:
results = executor.map(get_data, nums)
print()
for result in results:
print(result)
if __name__ == '__main__':
main()
futures
ejecutar en 4 threads
import threading
from concurrent import futures
from random import random
from time import sleep
import requests
nums = range(1, 11)
url_tpl = "http://jsonplaceholder.typicode.com/todos/{}"
def get_data(myid):
url = url_tpl.format(myid)
data = requests.get(url).json()
sleep(random() * 5)
return data
def main():
with futures.ThreadPoolExecutor(4) as executor:
results = executor.map(get_data, nums)
print()
for result in results:
print(result)
if __name__ == '__main__':
main()
futures
¡librerías síncronas!
def main():
# with futures.ProcessPoolExecutor(4) as executor:
with futures.ThreadPoolExecutor(4) as executor:
jobs = [executor.submit(get_data, num) for num in nums]
for comp_job in futures.as_completed(jobs):
print(comp_job.result())
futures
resultados según están
disponibles
def main():
with futures.ThreadPoolExecutor(5) as executor:
jobs = [executor.submit(get_img, num) for num in range(20)]
for comp_job in futures.as_completed(jobs):
img_path = comp_job.result()
executor.submit(add_meme_to_img, img_path)
futures
pasos encadenados
def main():
# with futures.ProcessPoolExecutor(4) as executor:
with futures.ThreadPoolExecutor(4) as executor:
jobs = [executor.submit(get_data, num) for num in nums]
done, not_done = futures.wait(jobs, return_when=futures.FIRST_COMPLETED)
print(done.pop().result())
print(len(not_done))
for not_done_job in not_done:
not_done_job.cancel()
print()
print('finished')
futures
“carreras” de futuros
¿y lo de la thread-safety?
• evitar los efectos secundarios o variables compartidas
• funciones puras - programación funcional
• cuidado con las librerías que usamos, pueden no ser thread-safe
Opciones
• Multithreading
• Multiprocessing
• Cooperative concurrency Async/Await
• concurrent.futures
• Tornado/Twisted
• Curio/Trio
• Django 3.x ?
¿y qué pasa con Django?
vistas con múlfples
llamadas I/O
(disco/red/bd)
vistas con múlfples
llamadas I/O
(disco/red/bd)
Asincronía en Django
tareas de larga
duración
fuera del ciclo de
request/response
websockets con
muchos clientes
¡ESTO!
async/await
celery
Django 3.0
async!
todavía no
https://www.aeracode.org/2018/06/04/django-async-roadmap/
Request path
• WSGI - ASGI handler
• URL routing
• Middlewares
• Views
ORM
Templates
Forms
Caching
Sessions
Authentication
Admin
Email
Static files
Signals
DjangoCon 2019 - Just Add Await: Retrofitting Async Into Django by Andrew Godwin https://www.youtube.com/watch?v=d9BAUBEyFgM
Async Django
• https://www.aeracode.org/2018/06/04/django-async-roadmap/
Timeline
• Python 3.2 (2011-02-20)
• concurrent.futures
• Python 3.4 (2014-03-16)
• asyncio provisional
• Python 3.5 (2015-09-13)
• PEP 492, coroufnes with async and await syntax.
• Python 3.6 (2016-12-23)
• PEP 525: Asynchronous Generators
• PEP 530: Asynchronous Comprehensions
• asyncio stable
• Python 3.7 (2018-06-27)
• asyncio faceli|
• Python 3.8 (2019-10-14)
• async REPL
• Twisted (2003)
• Netty (2004)
• Java
• Node.js (2009)
• JavaScript
• non-blocking by default
• npm
• Tornado (2010)
resumiendo
• el mundo es asíncrono
• muchas aplicaciones son I/O bound
• podemos usar mejor los recursos:
• multi-proceso,
• multi-thread
• concurrencia cooperativa
• cada tarea se puede completar en menos tiempo
• paralelizar acciones necesarias para completar una tarea (a veces)
• con los mismos recursos puedo ejecutar más tareas
• paralelizar acciones necesarias para múltiples tareas
¡muchas gracias!
¿preguntas?

More Related Content

What's hot

Working with NS2
Working with NS2Working with NS2
Working with NS2chanchal214
 
Степан Кольцов — Rust — лучше, чем C++
Степан Кольцов — Rust — лучше, чем C++Степан Кольцов — Rust — лучше, чем C++
Степан Кольцов — Rust — лучше, чем C++Yandex
 
"PostgreSQL and Python" Lightning Talk @EuroPython2014
"PostgreSQL and Python" Lightning Talk @EuroPython2014"PostgreSQL and Python" Lightning Talk @EuroPython2014
"PostgreSQL and Python" Lightning Talk @EuroPython2014Henning Jacobs
 
ClojureScript loves React, DomCode May 26 2015
ClojureScript loves React, DomCode May 26 2015ClojureScript loves React, DomCode May 26 2015
ClojureScript loves React, DomCode May 26 2015Michiel Borkent
 
NativeBoost
NativeBoostNativeBoost
NativeBoostESUG
 
Java Concurrency Idioms
Java Concurrency IdiomsJava Concurrency Idioms
Java Concurrency IdiomsAlex Miller
 
The Ring programming language version 1.7 book - Part 52 of 196
The Ring programming language version 1.7 book - Part 52 of 196The Ring programming language version 1.7 book - Part 52 of 196
The Ring programming language version 1.7 book - Part 52 of 196Mahmoud Samir Fayed
 
ClojureScript for the web
ClojureScript for the webClojureScript for the web
ClojureScript for the webMichiel Borkent
 
Chatting dengan beberapa pc laptop
Chatting dengan beberapa pc laptopChatting dengan beberapa pc laptop
Chatting dengan beberapa pc laptopyayaria
 
Rust: код может быть одновременно безопасным и быстрым, Степан Кольцов
Rust: код может быть одновременно безопасным и быстрым, Степан КольцовRust: код может быть одновременно безопасным и быстрым, Степан Кольцов
Rust: код может быть одновременно безопасным и быстрым, Степан КольцовYandex
 
.NET Multithreading and File I/O
.NET Multithreading and File I/O.NET Multithreading and File I/O
.NET Multithreading and File I/OJussi Pohjolainen
 
The Ruby Guide to *nix Plumbing: on the quest for efficiency with Ruby [M|K]RI
The Ruby Guide to *nix Plumbing: on the quest for efficiency with Ruby [M|K]RIThe Ruby Guide to *nix Plumbing: on the quest for efficiency with Ruby [M|K]RI
The Ruby Guide to *nix Plumbing: on the quest for efficiency with Ruby [M|K]RIEleanor McHugh
 
От Java Threads к лямбдам, Андрей Родионов
От Java Threads к лямбдам, Андрей РодионовОт Java Threads к лямбдам, Андрей Родионов
От Java Threads к лямбдам, Андрей РодионовYandex
 
An Introduction to Fluent & MongoDB Plugins
An Introduction to Fluent & MongoDB PluginsAn Introduction to Fluent & MongoDB Plugins
An Introduction to Fluent & MongoDB PluginsTakahiro Inoue
 
How to Avoid Common Mistakes When Using Reactor Netty
How to Avoid Common Mistakes When Using Reactor NettyHow to Avoid Common Mistakes When Using Reactor Netty
How to Avoid Common Mistakes When Using Reactor NettyVMware Tanzu
 
TDC2018SP | Trilha Kotlin - Programacao assincrona utilizando Coroutines
TDC2018SP | Trilha Kotlin - Programacao assincrona utilizando CoroutinesTDC2018SP | Trilha Kotlin - Programacao assincrona utilizando Coroutines
TDC2018SP | Trilha Kotlin - Programacao assincrona utilizando Coroutinestdc-globalcode
 

What's hot (20)

Working with NS2
Working with NS2Working with NS2
Working with NS2
 
Hadoop + Clojure
Hadoop + ClojureHadoop + Clojure
Hadoop + Clojure
 
Степан Кольцов — Rust — лучше, чем C++
Степан Кольцов — Rust — лучше, чем C++Степан Кольцов — Rust — лучше, чем C++
Степан Кольцов — Rust — лучше, чем C++
 
System Calls
System CallsSystem Calls
System Calls
 
"PostgreSQL and Python" Lightning Talk @EuroPython2014
"PostgreSQL and Python" Lightning Talk @EuroPython2014"PostgreSQL and Python" Lightning Talk @EuroPython2014
"PostgreSQL and Python" Lightning Talk @EuroPython2014
 
ClojureScript loves React, DomCode May 26 2015
ClojureScript loves React, DomCode May 26 2015ClojureScript loves React, DomCode May 26 2015
ClojureScript loves React, DomCode May 26 2015
 
NativeBoost
NativeBoostNativeBoost
NativeBoost
 
Java Concurrency Idioms
Java Concurrency IdiomsJava Concurrency Idioms
Java Concurrency Idioms
 
The Ring programming language version 1.7 book - Part 52 of 196
The Ring programming language version 1.7 book - Part 52 of 196The Ring programming language version 1.7 book - Part 52 of 196
The Ring programming language version 1.7 book - Part 52 of 196
 
C++ L08-Classes Part1
C++ L08-Classes Part1C++ L08-Classes Part1
C++ L08-Classes Part1
 
ClojureScript for the web
ClojureScript for the webClojureScript for the web
ClojureScript for the web
 
Chatting dengan beberapa pc laptop
Chatting dengan beberapa pc laptopChatting dengan beberapa pc laptop
Chatting dengan beberapa pc laptop
 
Rust: код может быть одновременно безопасным и быстрым, Степан Кольцов
Rust: код может быть одновременно безопасным и быстрым, Степан КольцовRust: код может быть одновременно безопасным и быстрым, Степан Кольцов
Rust: код может быть одновременно безопасным и быстрым, Степан Кольцов
 
.NET Multithreading and File I/O
.NET Multithreading and File I/O.NET Multithreading and File I/O
.NET Multithreading and File I/O
 
The Ruby Guide to *nix Plumbing: on the quest for efficiency with Ruby [M|K]RI
The Ruby Guide to *nix Plumbing: on the quest for efficiency with Ruby [M|K]RIThe Ruby Guide to *nix Plumbing: on the quest for efficiency with Ruby [M|K]RI
The Ruby Guide to *nix Plumbing: on the quest for efficiency with Ruby [M|K]RI
 
От Java Threads к лямбдам, Андрей Родионов
От Java Threads к лямбдам, Андрей РодионовОт Java Threads к лямбдам, Андрей Родионов
От Java Threads к лямбдам, Андрей Родионов
 
An Introduction to Fluent & MongoDB Plugins
An Introduction to Fluent & MongoDB PluginsAn Introduction to Fluent & MongoDB Plugins
An Introduction to Fluent & MongoDB Plugins
 
How to Avoid Common Mistakes When Using Reactor Netty
How to Avoid Common Mistakes When Using Reactor NettyHow to Avoid Common Mistakes When Using Reactor Netty
How to Avoid Common Mistakes When Using Reactor Netty
 
TDC2018SP | Trilha Kotlin - Programacao assincrona utilizando Coroutines
TDC2018SP | Trilha Kotlin - Programacao assincrona utilizando CoroutinesTDC2018SP | Trilha Kotlin - Programacao assincrona utilizando Coroutines
TDC2018SP | Trilha Kotlin - Programacao assincrona utilizando Coroutines
 
分散式系統
分散式系統分散式系統
分散式系統
 

Similar to Python Asíncrono - Async Python

Hands on Session on Python
Hands on Session on PythonHands on Session on Python
Hands on Session on PythonSumit Raj
 
Make Sure Your Applications Crash
Make Sure Your  Applications CrashMake Sure Your  Applications Crash
Make Sure Your Applications CrashMoshe Zadka
 
Spark with Elasticsearch - umd version 2014
Spark with Elasticsearch - umd version 2014Spark with Elasticsearch - umd version 2014
Spark with Elasticsearch - umd version 2014Holden Karau
 
The Ring programming language version 1.5.4 book - Part 40 of 185
The Ring programming language version 1.5.4 book - Part 40 of 185The Ring programming language version 1.5.4 book - Part 40 of 185
The Ring programming language version 1.5.4 book - Part 40 of 185Mahmoud Samir Fayed
 
RubyEnRails2007 - Dr Nic Williams - DIY Syntax
RubyEnRails2007 - Dr Nic Williams - DIY SyntaxRubyEnRails2007 - Dr Nic Williams - DIY Syntax
RubyEnRails2007 - Dr Nic Williams - DIY SyntaxDr Nic Williams
 
FS2 for Fun and Profit
FS2 for Fun and ProfitFS2 for Fun and Profit
FS2 for Fun and ProfitAdil Akhter
 
Threads Advance in System Administration with Linux
Threads Advance in System Administration with LinuxThreads Advance in System Administration with Linux
Threads Advance in System Administration with LinuxSoumen Santra
 
Jan Stępień - GraalVM: Fast, Polyglot, Native - Codemotion Berlin 2018
Jan Stępień - GraalVM: Fast, Polyglot, Native - Codemotion Berlin 2018Jan Stępień - GraalVM: Fast, Polyglot, Native - Codemotion Berlin 2018
Jan Stępień - GraalVM: Fast, Polyglot, Native - Codemotion Berlin 2018Codemotion
 
Chapter 5 - THREADING & REGULAR exp - MAULIK BORSANIYA
Chapter 5 - THREADING & REGULAR exp - MAULIK BORSANIYAChapter 5 - THREADING & REGULAR exp - MAULIK BORSANIYA
Chapter 5 - THREADING & REGULAR exp - MAULIK BORSANIYAMaulik Borsaniya
 
What's new in Python 3.11
What's new in Python 3.11What's new in Python 3.11
What's new in Python 3.11Henry Schreiner
 
sonam Kumari python.ppt
sonam Kumari python.pptsonam Kumari python.ppt
sonam Kumari python.pptssuserd64918
 
CONFidence 2015: DTrace + OSX = Fun - Andrzej Dyjak
CONFidence 2015: DTrace + OSX = Fun - Andrzej Dyjak   CONFidence 2015: DTrace + OSX = Fun - Andrzej Dyjak
CONFidence 2015: DTrace + OSX = Fun - Andrzej Dyjak PROIDEA
 
III MCS python lab (1).pdf
III MCS python lab (1).pdfIII MCS python lab (1).pdf
III MCS python lab (1).pdfsrxerox
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with ClojureDmitry Buzdin
 
اسلاید ارائه اول جلسه ۱۰ کلاس پایتون برای هکر های قانونی
اسلاید ارائه اول جلسه ۱۰ کلاس پایتون برای هکر های قانونی اسلاید ارائه اول جلسه ۱۰ کلاس پایتون برای هکر های قانونی
اسلاید ارائه اول جلسه ۱۰ کلاس پایتون برای هکر های قانونی Mohammad Reza Kamalifard
 
ODU ACM Python & Memento Presentation
ODU ACM Python & Memento PresentationODU ACM Python & Memento Presentation
ODU ACM Python & Memento PresentationScottAinsworth
 
Marrow: A Meta-Framework for Python 2.6+ and 3.1+
Marrow: A Meta-Framework for Python 2.6+ and 3.1+Marrow: A Meta-Framework for Python 2.6+ and 3.1+
Marrow: A Meta-Framework for Python 2.6+ and 3.1+ConFoo
 
The Ring programming language version 1.9 book - Part 56 of 210
The Ring programming language version 1.9 book - Part 56 of 210The Ring programming language version 1.9 book - Part 56 of 210
The Ring programming language version 1.9 book - Part 56 of 210Mahmoud Samir Fayed
 

Similar to Python Asíncrono - Async Python (20)

Hands on Session on Python
Hands on Session on PythonHands on Session on Python
Hands on Session on Python
 
Make Sure Your Applications Crash
Make Sure Your  Applications CrashMake Sure Your  Applications Crash
Make Sure Your Applications Crash
 
go.ppt
go.pptgo.ppt
go.ppt
 
Spark with Elasticsearch - umd version 2014
Spark with Elasticsearch - umd version 2014Spark with Elasticsearch - umd version 2014
Spark with Elasticsearch - umd version 2014
 
The Ring programming language version 1.5.4 book - Part 40 of 185
The Ring programming language version 1.5.4 book - Part 40 of 185The Ring programming language version 1.5.4 book - Part 40 of 185
The Ring programming language version 1.5.4 book - Part 40 of 185
 
RubyEnRails2007 - Dr Nic Williams - DIY Syntax
RubyEnRails2007 - Dr Nic Williams - DIY SyntaxRubyEnRails2007 - Dr Nic Williams - DIY Syntax
RubyEnRails2007 - Dr Nic Williams - DIY Syntax
 
FS2 for Fun and Profit
FS2 for Fun and ProfitFS2 for Fun and Profit
FS2 for Fun and Profit
 
Threads Advance in System Administration with Linux
Threads Advance in System Administration with LinuxThreads Advance in System Administration with Linux
Threads Advance in System Administration with Linux
 
Jan Stępień - GraalVM: Fast, Polyglot, Native - Codemotion Berlin 2018
Jan Stępień - GraalVM: Fast, Polyglot, Native - Codemotion Berlin 2018Jan Stępień - GraalVM: Fast, Polyglot, Native - Codemotion Berlin 2018
Jan Stępień - GraalVM: Fast, Polyglot, Native - Codemotion Berlin 2018
 
Chapter 5 - THREADING & REGULAR exp - MAULIK BORSANIYA
Chapter 5 - THREADING & REGULAR exp - MAULIK BORSANIYAChapter 5 - THREADING & REGULAR exp - MAULIK BORSANIYA
Chapter 5 - THREADING & REGULAR exp - MAULIK BORSANIYA
 
What's new in Python 3.11
What's new in Python 3.11What's new in Python 3.11
What's new in Python 3.11
 
sonam Kumari python.ppt
sonam Kumari python.pptsonam Kumari python.ppt
sonam Kumari python.ppt
 
Python programming : Threads
Python programming : ThreadsPython programming : Threads
Python programming : Threads
 
CONFidence 2015: DTrace + OSX = Fun - Andrzej Dyjak
CONFidence 2015: DTrace + OSX = Fun - Andrzej Dyjak   CONFidence 2015: DTrace + OSX = Fun - Andrzej Dyjak
CONFidence 2015: DTrace + OSX = Fun - Andrzej Dyjak
 
III MCS python lab (1).pdf
III MCS python lab (1).pdfIII MCS python lab (1).pdf
III MCS python lab (1).pdf
 
Refactoring to Macros with Clojure
Refactoring to Macros with ClojureRefactoring to Macros with Clojure
Refactoring to Macros with Clojure
 
اسلاید ارائه اول جلسه ۱۰ کلاس پایتون برای هکر های قانونی
اسلاید ارائه اول جلسه ۱۰ کلاس پایتون برای هکر های قانونی اسلاید ارائه اول جلسه ۱۰ کلاس پایتون برای هکر های قانونی
اسلاید ارائه اول جلسه ۱۰ کلاس پایتون برای هکر های قانونی
 
ODU ACM Python & Memento Presentation
ODU ACM Python & Memento PresentationODU ACM Python & Memento Presentation
ODU ACM Python & Memento Presentation
 
Marrow: A Meta-Framework for Python 2.6+ and 3.1+
Marrow: A Meta-Framework for Python 2.6+ and 3.1+Marrow: A Meta-Framework for Python 2.6+ and 3.1+
Marrow: A Meta-Framework for Python 2.6+ and 3.1+
 
The Ring programming language version 1.9 book - Part 56 of 210
The Ring programming language version 1.9 book - Part 56 of 210The Ring programming language version 1.9 book - Part 56 of 210
The Ring programming language version 1.9 book - Part 56 of 210
 

More from Javier Abadía

Extendiendo Django: Cómo Escribir Tu Propio Backend de Base de Datos - Exasol
Extendiendo Django: Cómo Escribir Tu Propio Backend de Base de Datos - ExasolExtendiendo Django: Cómo Escribir Tu Propio Backend de Base de Datos - Exasol
Extendiendo Django: Cómo Escribir Tu Propio Backend de Base de Datos - ExasolJavier Abadía
 
UX/UI para Desarrolladores
UX/UI para DesarrolladoresUX/UI para Desarrolladores
UX/UI para DesarrolladoresJavier Abadía
 
Reactividad en Angular, React y VueJS
Reactividad en Angular, React y VueJSReactividad en Angular, React y VueJS
Reactividad en Angular, React y VueJSJavier Abadía
 
Las reglas que hay que romper para que tu equipo de desarrollo sea el más RÁPIDO
Las reglas que hay que romper para que tu equipo de desarrollo sea el más RÁPIDOLas reglas que hay que romper para que tu equipo de desarrollo sea el más RÁPIDO
Las reglas que hay que romper para que tu equipo de desarrollo sea el más RÁPIDOJavier Abadía
 
Retos de Programación en Python
Retos de Programación en PythonRetos de Programación en Python
Retos de Programación en PythonJavier Abadía
 
Django + Vue, JavaScript de 3ª generación para modernizar Django
Django + Vue, JavaScript de 3ª generación para modernizar DjangoDjango + Vue, JavaScript de 3ª generación para modernizar Django
Django + Vue, JavaScript de 3ª generación para modernizar DjangoJavier Abadía
 
Vue.js + Django - configuración para desarrollo con webpack y HMR
Vue.js + Django - configuración para desarrollo con webpack y HMRVue.js + Django - configuración para desarrollo con webpack y HMR
Vue.js + Django - configuración para desarrollo con webpack y HMRJavier Abadía
 
Anatomía de un Bot para Resultados Electorales
Anatomía de un Bot para Resultados ElectoralesAnatomía de un Bot para Resultados Electorales
Anatomía de un Bot para Resultados ElectoralesJavier Abadía
 
Deep learning image classification aplicado al mundo de la moda
Deep learning image classification aplicado al mundo de la modaDeep learning image classification aplicado al mundo de la moda
Deep learning image classification aplicado al mundo de la modaJavier Abadía
 
Análisis de colores: cómo analizar tendencias de moda automáticamente
 Análisis de colores: cómo analizar tendencias de moda automáticamente Análisis de colores: cómo analizar tendencias de moda automáticamente
Análisis de colores: cómo analizar tendencias de moda automáticamenteJavier Abadía
 
Codemotion 2016 - d3.js un taller divertido y difícil
Codemotion 2016 - d3.js un taller divertido y difícilCodemotion 2016 - d3.js un taller divertido y difícil
Codemotion 2016 - d3.js un taller divertido y difícilJavier Abadía
 

More from Javier Abadía (12)

Extendiendo Django: Cómo Escribir Tu Propio Backend de Base de Datos - Exasol
Extendiendo Django: Cómo Escribir Tu Propio Backend de Base de Datos - ExasolExtendiendo Django: Cómo Escribir Tu Propio Backend de Base de Datos - Exasol
Extendiendo Django: Cómo Escribir Tu Propio Backend de Base de Datos - Exasol
 
UX/UI para Desarrolladores
UX/UI para DesarrolladoresUX/UI para Desarrolladores
UX/UI para Desarrolladores
 
Reactividad en Angular, React y VueJS
Reactividad en Angular, React y VueJSReactividad en Angular, React y VueJS
Reactividad en Angular, React y VueJS
 
Las reglas que hay que romper para que tu equipo de desarrollo sea el más RÁPIDO
Las reglas que hay que romper para que tu equipo de desarrollo sea el más RÁPIDOLas reglas que hay que romper para que tu equipo de desarrollo sea el más RÁPIDO
Las reglas que hay que romper para que tu equipo de desarrollo sea el más RÁPIDO
 
Retos de Programación en Python
Retos de Programación en PythonRetos de Programación en Python
Retos de Programación en Python
 
Django + Vue, JavaScript de 3ª generación para modernizar Django
Django + Vue, JavaScript de 3ª generación para modernizar DjangoDjango + Vue, JavaScript de 3ª generación para modernizar Django
Django + Vue, JavaScript de 3ª generación para modernizar Django
 
Vue.js + Django - configuración para desarrollo con webpack y HMR
Vue.js + Django - configuración para desarrollo con webpack y HMRVue.js + Django - configuración para desarrollo con webpack y HMR
Vue.js + Django - configuración para desarrollo con webpack y HMR
 
Anatomía de un Bot para Resultados Electorales
Anatomía de un Bot para Resultados ElectoralesAnatomía de un Bot para Resultados Electorales
Anatomía de un Bot para Resultados Electorales
 
Deep learning image classification aplicado al mundo de la moda
Deep learning image classification aplicado al mundo de la modaDeep learning image classification aplicado al mundo de la moda
Deep learning image classification aplicado al mundo de la moda
 
Análisis de colores: cómo analizar tendencias de moda automáticamente
 Análisis de colores: cómo analizar tendencias de moda automáticamente Análisis de colores: cómo analizar tendencias de moda automáticamente
Análisis de colores: cómo analizar tendencias de moda automáticamente
 
Codemotion 2016 - d3.js un taller divertido y difícil
Codemotion 2016 - d3.js un taller divertido y difícilCodemotion 2016 - d3.js un taller divertido y difícil
Codemotion 2016 - d3.js un taller divertido y difícil
 
La Noche Electoral
La Noche ElectoralLa Noche Electoral
La Noche Electoral
 

Recently uploaded

Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxbodapatigopi8531
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)OPEN KNOWLEDGE GmbH
 
Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackVICTOR MAESTRE RAMIREZ
 
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...Christina Lin
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...MyIntelliSource, Inc.
 
Project Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationProject Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationkaushalgiri8080
 
XpertSolvers: Your Partner in Building Innovative Software Solutions
XpertSolvers: Your Partner in Building Innovative Software SolutionsXpertSolvers: Your Partner in Building Innovative Software Solutions
XpertSolvers: Your Partner in Building Innovative Software SolutionsMehedi Hasan Shohan
 
Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...aditisharan08
 
Asset Management Software - Infographic
Asset Management Software - InfographicAsset Management Software - Infographic
Asset Management Software - InfographicHr365.us smith
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideChristina Lin
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...gurkirankumar98700
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comFatema Valibhai
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWave PLM
 
The Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdfThe Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdfPower Karaoke
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...stazi3110
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsAlberto González Trastoy
 
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxKnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxTier1 app
 
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfThe Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfkalichargn70th171
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio, Inc.
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVshikhaohhpro
 

Recently uploaded (20)

Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptx
 
Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)Der Spagat zwischen BIAS und FAIRNESS (2024)
Der Spagat zwischen BIAS und FAIRNESS (2024)
 
Cloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStackCloud Management Software Platforms: OpenStack
Cloud Management Software Platforms: OpenStack
 
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
ODSC - Batch to Stream workshop - integration of Apache Spark, Cassandra, Pos...
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
 
Project Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationProject Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanation
 
XpertSolvers: Your Partner in Building Innovative Software Solutions
XpertSolvers: Your Partner in Building Innovative Software SolutionsXpertSolvers: Your Partner in Building Innovative Software Solutions
XpertSolvers: Your Partner in Building Innovative Software Solutions
 
Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...
 
Asset Management Software - Infographic
Asset Management Software - InfographicAsset Management Software - Infographic
Asset Management Software - Infographic
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.com
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need It
 
The Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdfThe Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdf
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
 
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptxKnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
KnowAPIs-UnknownPerf-jaxMainz-2024 (1).pptx
 
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfThe Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
 
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed DataAlluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
Alluxio Monthly Webinar | Cloud-Native Model Training on Distributed Data
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 

Python Asíncrono - Async Python

  • 1. Python Asíncrono ¿echas de menos las promesas? @javierabadia
  • 3.
  • 5.
  • 6.
  • 7. Javier Abadía VP of Engineering @ StyleSage
  • 8.
  • 10. claves de diccionarios funciones anónimas asincronía
  • 11. ❤ const API_URL = `https://api.openweathermap.org/data/2.5/weather?appid=${API_KEY}&units=metric`; // list of cities const CITIES = [ 'London', 'Tokyo', 'Melbourne', 'Vancouver', 'Lagos', 'Berlin', 'Paris', 'Johannesburg', 'Chicago', 'Mumbai', 'Cairo', 'Beijing' ]; const fetchTemperatureForCity = city => { // For example: ['Lagos', 29.28] return fetch(`${API_URL}&q=${encodeURIComponent(city)}`) .then(response => response.json()) .then(data => [ city, data.main.temp || null ]); } const fetchTemperatureForCities = cities => { return Promise.all(cities.map(fetchTemperatureForCity)) .then(temps => { return temps.reduce((data, [ city, temp ]) => { return { ...data, [city]: Number.isFinite(temp) ? temp.toFixed(2) * 1 : null }; }, {}); }); } fetchTemperatureForCities(CITIES) .then(console.log, console.error);
  • 12. si tuviera que hacer esto en una vista de Django… …no sabría
  • 13. Si Python fuera un bar… BAR
  • 14. BAR Una Hamburguesa, con patatas grandes y una cerveza, por favor Enseguida! esperar esperar servir la cerveza pedir la hamburguesa a la cocina poner las patatatas a freir sacar las patatas de la freidora 1 cliente = 10 min
  • 15. BAR esperar poner las patatatas a freir pedir la hamburguesa a la cocina esperar servir la cerveza sacar las patatas de la freidora esperar poner las patatatas a freir pedir la hamburguesa a la cocina esperar servir la cerveza sacar las patatas de la freidora esperar poner las patatatas a freir pedir la hamburguesa a la cocina esperar servir la cerveza sacar las patatas de la freidora 3 clientes (10, 20, 30) ⋍ 20 min
  • 16. atender más clientes a la vez esperar poner las patatatas a freir pedir la hamburguesa a la cocina esperar servir la cerveza sacar las patatas de la freidora esperar poner las patatatas a freir pedir la hamburguesa a la cocina esperar servir la cerveza sacar las patatas de la freidora esperar poner las patatatas a freir pedir la hamburguesa a la cocina esperar servir la cerveza sacar las patatas de la freidora atender a un cliente en menos tiempo hacer un mejor uso de los recursos
  • 17.
  • 19. Tiempos System Event Actual Latency Scaled Latency One CPU cycle 0.4 ns 1 s Level 1 cache access 0.9 ns 2 s Level 2 cache access 2.8 ns 7 s Level 3 cache access 28 ns 1 min Main memory access (DDR DIMM) ~100 ns 4 min NVMe SSD I/O ~25 μs 17 hrs SSD I/O 50–150 μs 1.5 - 4 days Rotational disk I/O 1–10 ms 1-9 months Internet call: San Francisco to New York City 65 ms 5 years Internet call: San Francisco to Hong Kong 141 ms 11 years
  • 20. url = 'http://example.com/david-hasselhoff.jpg' path = 'media/cool-pics/screen-background.jpg’ r = requests.get(url, stream=True) if r.status_code == 200: with open(path, 'wb') as f: for chunk in r.iter_content(1024): f.write(chunk) im = Image.open(path) im.thumbnail(size, Image.ANTIALIAS) im.save(thumbnail_path, "JPEG") pic = CoolPics(img=path, thumbnail=thumbnail_path) pic.save() varios años varios meses varios meses varios meses varios meses unas pocas horas varios meses < de una hora varios meses
  • 21. url = 'http://example.com/david-hasselhoff.jpg' path = 'media/cool-pics/screen-background.jpg’ r = requests.get(url, stream=True) if r.status_code == 200: with open(path, 'wb') as f: for chunk in r.iter_content(1024): f.write(chunk) im = Image.open(path) im.thumbnail(size, Image.ANTIALIAS) im.save(thumbnail_path, "JPEG") pic = CoolPics(img=path, thumbnail=thumbnail_path) pic.save() varios años varios meses varios meses varios meses varios meses unas pocas horas varios meses < de una hora varios meses naturalezasecuencial x 2000
  • 23. BAR esperar poner las patatatas a freir pedir la hamburguesa a la cocina esperar servir la cerveza sacar las patatas de la freidora esperar poner las patatatas a freir pedir la hamburguesa a la cocina esperar servir la cerveza sacar las patatas de la freidora esperar poner las patatatas a freir pedir la hamburguesa a la cocina esperar servir la cerveza sacar las patatas de la freidora 3 clientes (10, 12, 20) ⋍ 14 min
  • 24. import threading import time class MyThread(threading.Thread): def __init__(self, thread_id, name, delay): super().__init__() self.thread_id = thread_id self.name = name self.delay = delay def run(self): print("Starting " + self.name) # Get lock to synchronize threads # g_thread_lock.acquire() print_time(self.name, 3, self.delay) # Free lock to release next thread # g_thread_lock.release() def print_time(thread_name, counter, delay): while counter: time.sleep(delay) print("%s: %s" % ( thread_name, time.ctime(time.time())) ) counter -= 1 # … # … g_thread_lock = threading.Lock() threads = [] # Create new threads thread1 = MyThread(1, "Thread-1", 1) thread2 = MyThread(2, "Thread-2", 2) # Start new Threads thread1.start() thread2.start() # Add threads to thread list threads.append(thread1) threads.append(thread2) # Wait for all threads to complete for t in threads: t.join() print("Exiting Main Thread") threading
  • 25. import threading import time class MyThread(threading.Thread): def __init__(self, thread_id, name, delay): super().__init__() self.thread_id = thread_id self.name = name self.delay = delay def run(self): print("Starting " + self.name) # Get lock to synchronize threads # g_thread_lock.acquire() print_time(self.name, 3, self.delay) # Free lock to release next thread # g_thread_lock.release() def print_time(thread_name, counter, delay): while counter: time.sleep(delay) print("%s: %s" % ( thread_name, time.ctime(time.time())) ) counter -= 1 # … # … g_thread_lock = threading.Lock() threads = [] # Create new threads thread1 = MyThread(1, "Thread-1", 1) thread2 = MyThread(2, "Thread-2", 2) # Start new Threads thread1.start() thread2.start() # Add threads to thread list threads.append(thread1) threads.append(thread2) # Wait for all threads to complete for t in threads: t.join() print("Exiting Main Thread") crear las threads
  • 26. import threading import time class MyThread(threading.Thread): def __init__(self, thread_id, name, delay): super().__init__() self.thread_id = thread_id self.name = name self.delay = delay def run(self): print("Starting " + self.name) # Get lock to synchronize threads # g_thread_lock.acquire() print_time(self.name, 3, self.delay) # Free lock to release next thread # g_thread_lock.release() def print_time(thread_name, counter, delay): while counter: time.sleep(delay) print("%s: %s" % ( thread_name, time.ctime(time.time())) ) counter -= 1 # … # … g_thread_lock = threading.Lock() threads = [] # Create new threads thread1 = MyThread(1, "Thread-1", 1) thread2 = MyThread(2, "Thread-2", 2) # Start new Threads thread1.start() thread2.start() # Add threads to thread list threads.append(thread1) threads.append(thread2) # Wait for all threads to complete for t in threads: t.join() print("Exiting Main Thread") arrancarlas
  • 27. import threading import time class MyThread(threading.Thread): def __init__(self, thread_id, name, delay): super().__init__() self.thread_id = thread_id self.name = name self.delay = delay def run(self): print("Starting " + self.name) # Get lock to synchronize threads # g_thread_lock.acquire() print_time(self.name, 3, self.delay) # Free lock to release next thread # g_thread_lock.release() def print_time(thread_name, counter, delay): while counter: time.sleep(delay) print("%s: %s" % ( thread_name, time.ctime(time.time())) ) counter -= 1 # … # … g_thread_lock = threading.Lock() threads = [] # Create new threads thread1 = MyThread(1, "Thread-1", 1) thread2 = MyThread(2, "Thread-2", 2) # Start new Threads thread1.start() thread2.start() # Add threads to thread list threads.append(thread1) threads.append(thread2) # Wait for all threads to complete for t in threads: t.join() print("Exiting Main Thread") ¿sincronizarlas?
  • 28. import threading import time class MyThread(threading.Thread): def __init__(self, thread_id, name, delay): super().__init__() self.thread_id = thread_id self.name = name self.delay = delay def run(self): print("Starting " + self.name) # Get lock to synchronize threads # g_thread_lock.acquire() print_time(self.name, 3, self.delay) # Free lock to release next thread # g_thread_lock.release() def print_time(thread_name, counter, delay): while counter: time.sleep(delay) print("%s: %s" % ( thread_name, time.ctime(time.time())) ) counter -= 1 # … # … g_thread_lock = threading.Lock() threads = [] # Create new threads thread1 = MyThread(1, "Thread-1", 1) thread2 = MyThread(2, "Thread-2", 2) # Start new Threads thread1.start() thread2.start() # Add threads to thread list threads.append(thread1) threads.append(thread2) # Wait for all threads to complete for t in threads: t.join() print("Exiting Main Thread") esperar a que terminen
  • 29. thread safety hcp://edot.org/pyfaq/what-kinds-of-global-value-mutafon-are-thread-safe.htm songs = [] songs.append(my_song) songs.pop() songs.sort() artist_ages.keys() i = i+1 songs[i] = songs[j] if songs: song = songs.pop() artist_ages[‘Bob’] += 1
  • 30.
  • 34. BAR BAR esperar poner las patatatas a freir pedir la hamburguesa a la cocina esperar servir la cerveza sacar las patatas de la freidora esperar poner las patatatas a freir pedir la hamburguesa a la cocina esperar servir la cerveza sacar las patatas de la freidora esperar poner las patatatas a freir pedir la hamburguesa a la cocina esperar servir la cerveza sacar las patatas de la freidora 3 clientes (10, 10, 20) ⋍ 13.3 min
  • 35. from multiprocessing import Lock, Process, Queue, current_process import time import queue # imported for using queue.Empty exception def do_job(tasks_to_accomplish, tasks_that_are_done): while True: try: task = tasks_to_accomplish.get_nowait() except queue.Empty: break else: print(task) tasks_that_are_done.put(task + ' is done by ' + current_process().name) time.sleep(.5) return True def main(): number_of_task = 10 number_of_processes = 4 tasks_to_accomplish = Queue() tasks_that_are_done = Queue() processes = [] for i in range(number_of_task): tasks_to_accomplish.put("Task no " + str(i)) # creating processes for w in range(number_of_processes): p = Process( target=do_job, args=(tasks_to_accomplish, tasks_that_are_done) ) processes.append(p) p.start() # completing process for p in processes: p.join() # print the output while not tasks_that_are_done.empty(): print(tasks_that_are_done.get()) return True if __name__ == '__main__': main() mulf-processing
  • 36. from multiprocessing import Lock, Process, Queue, current_process import time import queue # imported for using queue.Empty exception def do_job(tasks_to_accomplish, tasks_that_are_done): while True: try: task = tasks_to_accomplish.get_nowait() except queue.Empty: break else: print(task) tasks_that_are_done.put(task + ' is done by ' + current_process().name) time.sleep(.5) return True def main(): number_of_task = 10 number_of_processes = 4 tasks_to_accomplish = Queue() tasks_that_are_done = Queue() processes = [] for i in range(number_of_task): tasks_to_accomplish.put("Task no " + str(i)) # creating processes for w in range(number_of_processes): p = Process( target=do_job, args=(tasks_to_accomplish, tasks_that_are_done) ) processes.append(p) p.start() # completing process for p in processes: p.join() # print the output while not tasks_that_are_done.empty(): print(tasks_that_are_done.get()) return True if __name__ == '__main__': main() multi-processing
  • 37. from multiprocessing import Lock, Process, Queue, current_process import time import queue # imported for using queue.Empty exception def do_job(tasks_to_accomplish, tasks_that_are_done): while True: try: task = tasks_to_accomplish.get_nowait() except queue.Empty: break else: print(task) tasks_that_are_done.put(task + ' is done by ' + current_process().name) time.sleep(.5) return True def main(): number_of_task = 10 number_of_processes = 4 tasks_to_accomplish = Queue() tasks_that_are_done = Queue() processes = [] for i in range(number_of_task): tasks_to_accomplish.put("Task no " + str(i)) # creating processes for w in range(number_of_processes): p = Process( target=do_job, args=(tasks_to_accomplish, tasks_that_are_done) ) processes.append(p) p.start() # completing process for p in processes: p.join() # print the output while not tasks_that_are_done.empty(): print(tasks_that_are_done.get()) return True if __name__ == '__main__': main() multi-processing crear colas IPC
  • 38. from multiprocessing import Lock, Process, Queue, current_process import time import queue # imported for using queue.Empty exception def do_job(tasks_to_accomplish, tasks_that_are_done): while True: try: task = tasks_to_accomplish.get_nowait() except queue.Empty: break else: print(task) tasks_that_are_done.put(task + ' is done by ' + current_process().name) time.sleep(.5) return True def main(): number_of_task = 10 number_of_processes = 4 tasks_to_accomplish = Queue() tasks_that_are_done = Queue() processes = [] for i in range(number_of_task): tasks_to_accomplish.put("Task no " + str(i)) # creating processes for w in range(number_of_processes): p = Process( target=do_job, args=(tasks_to_accomplish, tasks_that_are_done) ) processes.append(p) p.start() # completing process for p in processes: p.join() # print the output while not tasks_that_are_done.empty(): print(tasks_that_are_done.get()) return True if __name__ == '__main__': main() multi-processing crear los procesos
  • 39. from multiprocessing import Lock, Process, Queue, current_process import time import queue # imported for using queue.Empty exception def do_job(tasks_to_accomplish, tasks_that_are_done): while True: try: task = tasks_to_accomplish.get_nowait() except queue.Empty: break else: print(task) tasks_that_are_done.put(task + ' is done by ' + current_process().name) time.sleep(.5) return True def main(): number_of_task = 10 number_of_processes = 4 tasks_to_accomplish = Queue() tasks_that_are_done = Queue() processes = [] for i in range(number_of_task): tasks_to_accomplish.put("Task no " + str(i)) # creating processes for w in range(number_of_processes): p = Process( target=do_job, args=(tasks_to_accomplish, tasks_that_are_done) ) processes.append(p) p.start() # completing process for p in processes: p.join() # print the output while not tasks_that_are_done.empty(): print(tasks_that_are_done.get()) return True if __name__ == '__main__': main() multi-processing ejecutar los procesos
  • 40. from multiprocessing import Lock, Process, Queue, current_process import time import queue # imported for using queue.Empty exception def do_job(tasks_to_accomplish, tasks_that_are_done): while True: try: task = tasks_to_accomplish.get_nowait() except queue.Empty: break else: print(task) tasks_that_are_done.put(task + ' is done by ' + current_process().name) time.sleep(.5) return True def main(): number_of_task = 10 number_of_processes = 4 tasks_to_accomplish = Queue() tasks_that_are_done = Queue() processes = [] for i in range(number_of_task): tasks_to_accomplish.put("Task no " + str(i)) # creating processes for w in range(number_of_processes): p = Process( target=do_job, args=(tasks_to_accomplish, tasks_that_are_done) ) processes.append(p) p.start() # completing process for p in processes: p.join() # print the output while not tasks_that_are_done.empty(): print(tasks_that_are_done.get()) return True if __name__ == '__main__': main() multi-processing esperar a que terminen todos
  • 41. I/O bound CPU bound multi- threading mulf- processing comparten memoria GIL más pesados no comparten memoria IPC
  • 42. Global Interpreter Lock • El intérprete de Python no es thread-safe • Específico de ALGUNAS implementaciones de Python (CPython, PyPy) • Solo una thread puede estar interpretando código Python en un proceso • El intérprete “suelta” el “lock” para operaciones I/O (o incluso NumPy) • Consecuencias: • tareas limitadas por I/O van más rápido con múltiples threads • tareas limitadas por CPU van más lento con múltiples threads
  • 43. más rápido ¡más lento! (por culpa del GIL) más rápido (pero más ”caro”) más rápido I/O bound CPU bound multi- threading multi- processing comparten memoria GIL más pesados no comparten memoria IPC
  • 44. pero… ¿cómo lo hace JavaScript?
  • 45. BAR servir la cerveza pedir la hamburguesa a la cocina poner las patatatas a freir sacar las patatas de la freidora servir la cerveza pedir la hamburguesa a la cocina poner las patatatas a freir sacar las patatas de la freidora servir la cerveza pedir la hamburguesa a la cocina poner las patatatas a freir sacar las patatas de la freidora 3 clientes (4,5,7) ⋍ 5,33 min
  • 46. Modelo de Concurrencia de JavaScript • en JavaScript solo hay una thread de usuario • el código se ejecuta “por turnos”, sin ninguna interrupción, siempre hasta el final • dentro de un “bucle de eventos” • TODAS las operaciones de I/O son asíncronas: • se lanzan en el momento • el código no espera a que se termine la ejecución • el resultado se recibe en un callback (o una Promesa) que se ejecutará en un turno en el futuro • También son asíncronas todas las funciones que llaman a una función asíncrona https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop
  • 47.
  • 48.
  • 50. event loopevent loopevent loopevent loop TURNO 1 TURNO 2
  • 51. Python asyncio - async/await Python 3.4+
  • 52. # https://docs.python.org/3/library/asyncio-task.html import asyncio import time async def say_after(delay, what): await asyncio.sleep(delay) print(what) async def main(): print(f"started at {time.strftime('%X')}") await say_after(1, 'hello') await say_after(2, 'world') print(f"finished at {time.strftime('%X')}") asyncio.run(main()) bucle de eventos await ≈ yield
  • 53. import asyncio import time async def say_after(delay, what): await asyncio.sleep(delay) print(what) async def main(): print(f"started at {time.strftime('%X')}") t1 = say_after(1, 'hello') t2 = say_after(2, 'world') await asyncio.gather(t1, t2) print(f"finished at {time.strftime('%X')}") asyncio.run(main())
  • 56. si no hay cooperación, no funciona • en JavaScript la cooperación es obligatoria • todas las librerías son asíncronas • en Python casi todas las librerías son síncronas (no cooperan) nuestro código no debe bloquearse debe devolver el control al bucle de eventos no hay un “scheduler pre-emptivo”
  • 57. el problema es… • todo lo que NO podemos usar • http, requests • acceso a bases de datos • I/O de ficheros • necesitamos nuevas librerías para todo • aiohttp • aiopg • aiomysql • aiofiles • https://github.com/timofurrer/awesome-asyncio
  • 59. es difícil • converfr un proyecto existente en async • o una parte • en un nuevo proyecto async • encontrar y usar librerías • p.ej script que se conecta a nuestra cuenta de GitHub y crea un informe de branches en Excel • pygithub - hace llamadas de red • openpyxl - lee y escribe ficheros
  • 60.
  • 61.
  • 63. concurrent.futures • librería de alto nivel • usando multi-processing o multi-threading con la misma interfaz • proporciona una sintaxis parecida a las promesas • compatible con todas las librerías síncronas • si son thread-safe podemos usar multi-threading • si no, tendremos que usar multi-processing Python 3.22011-02-20
  • 64. import threading from concurrent import futures from random import random from time import sleep import requests nums = range(1, 11) url_tpl = "http://jsonplaceholder.typicode.com/todos/{}" def get_data(myid): url = url_tpl.format(myid) data = requests.get(url).json() sleep(random() * 5) return data def main(): with futures.ThreadPoolExecutor(4) as executor: results = executor.map(get_data, nums) print() for result in results: print(result) if __name__ == '__main__': main() futures
  • 65. import threading from concurrent import futures from random import random from time import sleep import requests nums = range(1, 11) url_tpl = "http://jsonplaceholder.typicode.com/todos/{}" def get_data(myid): url = url_tpl.format(myid) data = requests.get(url).json() sleep(random() * 5) return data def main(): with futures.ThreadPoolExecutor(4) as executor: results = executor.map(get_data, nums) print() for result in results: print(result) if __name__ == '__main__': main() futures ejecutar en 4 threads
  • 66. import threading from concurrent import futures from random import random from time import sleep import requests nums = range(1, 11) url_tpl = "http://jsonplaceholder.typicode.com/todos/{}" def get_data(myid): url = url_tpl.format(myid) data = requests.get(url).json() sleep(random() * 5) return data def main(): with futures.ThreadPoolExecutor(4) as executor: results = executor.map(get_data, nums) print() for result in results: print(result) if __name__ == '__main__': main() futures ¡librerías síncronas!
  • 67. def main(): # with futures.ProcessPoolExecutor(4) as executor: with futures.ThreadPoolExecutor(4) as executor: jobs = [executor.submit(get_data, num) for num in nums] for comp_job in futures.as_completed(jobs): print(comp_job.result()) futures resultados según están disponibles
  • 68. def main(): with futures.ThreadPoolExecutor(5) as executor: jobs = [executor.submit(get_img, num) for num in range(20)] for comp_job in futures.as_completed(jobs): img_path = comp_job.result() executor.submit(add_meme_to_img, img_path) futures pasos encadenados
  • 69. def main(): # with futures.ProcessPoolExecutor(4) as executor: with futures.ThreadPoolExecutor(4) as executor: jobs = [executor.submit(get_data, num) for num in nums] done, not_done = futures.wait(jobs, return_when=futures.FIRST_COMPLETED) print(done.pop().result()) print(len(not_done)) for not_done_job in not_done: not_done_job.cancel() print() print('finished') futures “carreras” de futuros
  • 70. ¿y lo de la thread-safety? • evitar los efectos secundarios o variables compartidas • funciones puras - programación funcional • cuidado con las librerías que usamos, pueden no ser thread-safe
  • 71. Opciones • Multithreading • Multiprocessing • Cooperative concurrency Async/Await • concurrent.futures • Tornado/Twisted • Curio/Trio • Django 3.x ?
  • 72. ¿y qué pasa con Django?
  • 73. vistas con múlfples llamadas I/O (disco/red/bd) vistas con múlfples llamadas I/O (disco/red/bd) Asincronía en Django tareas de larga duración fuera del ciclo de request/response websockets con muchos clientes ¡ESTO! async/await celery
  • 76. https://www.aeracode.org/2018/06/04/django-async-roadmap/ Request path • WSGI - ASGI handler • URL routing • Middlewares • Views ORM Templates Forms Caching Sessions Authentication Admin Email Static files Signals
  • 77. DjangoCon 2019 - Just Add Await: Retrofitting Async Into Django by Andrew Godwin https://www.youtube.com/watch?v=d9BAUBEyFgM
  • 79. Timeline • Python 3.2 (2011-02-20) • concurrent.futures • Python 3.4 (2014-03-16) • asyncio provisional • Python 3.5 (2015-09-13) • PEP 492, coroufnes with async and await syntax. • Python 3.6 (2016-12-23) • PEP 525: Asynchronous Generators • PEP 530: Asynchronous Comprehensions • asyncio stable • Python 3.7 (2018-06-27) • asyncio faceli| • Python 3.8 (2019-10-14) • async REPL • Twisted (2003) • Netty (2004) • Java • Node.js (2009) • JavaScript • non-blocking by default • npm • Tornado (2010)
  • 80. resumiendo • el mundo es asíncrono • muchas aplicaciones son I/O bound • podemos usar mejor los recursos: • multi-proceso, • multi-thread • concurrencia cooperativa • cada tarea se puede completar en menos tiempo • paralelizar acciones necesarias para completar una tarea (a veces) • con los mismos recursos puedo ejecutar más tareas • paralelizar acciones necesarias para múltiples tareas