Download - Programação Assíncrona com Asyncio
ALLISSON AZEVEDOallissonazevedo.com
youtube.com/user/allissonazevedo
github.com/allisson
twitter.com/allisson
linkedin.com/in/allisson/
allisson.github.io/slides/
2
THE C10K PROBLEMComo lidar com 10k conexões simultâneas
http://www.kegel.com/c10k.html
3
CONCORRÊNCIA
Asynchronous I/O
O exemplo do garçom
Não confundir com paralelismo
4
PROGRAMAÇÃO SÍNCRONAimport time import requests from github import REPOS, ACCESS_TOKEN
start = time.time() for repo_url in REPOS: response = requests.get(repo_url, params={'access_token': ACCESS_TOKEN}).json() repo_info = { 'name': response['name'], 'full_name': response['full_name'], 'stargazers_count': response['stargazers_count'] } print(repo_info) end = time.time() print('Tempo de execução={:.2f} segundos'.format(end - start))
5
CONCORRÊNCIA USANDO THREADSimport time import threading import queue import requests from github import REPOS, ACCESS_TOKEN
def grab_data_from_queue(): while not q.empty(): repo_url = q.get() response = requests.get(repo_url, params={'access_token' repo_info = { 'name': response['name'], 'full_name': response['full_name'], 'stargazers_count': response['stargazers_count'] }
7
PROBLEMAS COM THREADS
Consumo de recursos
Global Interpreter Lock (GIL)
8
CONCORRÊNCIA USANDO PROCESSimport time import multiprocessing import requests from github import REPOS, ACCESS_TOKEN
def grab_data_from_queue(): while not q.empty(): repo_url = q.get() response = requests.get(repo_url, params={'access_token' repo_info = { 'name': response['name'], 'full_name': response['full_name'], 'stargazers_count': response['stargazers_count'] } print(repo_info)
9
CONCORRÊNCIA USANDOCONCURRENT.FUTURES
import time from concurrent import futures import requests from github import REPOS, ACCESS_TOKEN
def get_repo_info(repo_url): response = requests.get(repo_url, params={'access_token': ACCESS_TOKEN}).json() repo_info = { 'name': response['name'], 'full_name': response['full_name'], 'stargazers_count': response['stargazers_count'] } print(repo_info)
11
PROBLEMAS COMCONCURRENT.FUTURES
ThreadPoolExecutor - usa threads
ProcessPoolExecutor - usa process
12
ASYNCHRONOUS I/O COM PYTHONTwisted
Tornado
Eventlet
Gevent
Asyncio
13
ASYNCIO
Python 3.4+
Tulip
PEP-3156
14
HELLO WORLDimport asyncio
async def hello_world(): print('Hello World!')
loop = asyncio.get_event_loop() loop.run_until_complete(hello_world())
15
HELLO WORLD COM TASKSimport asyncio
async def hello_world(name): print('Hello World, {}!'.format(name))
loop = asyncio.get_event_loop() tasks = [] for name in ('fulano', 'cicrano', 'beltrano'): task = asyncio.ensure_future(hello_world(name)) tasks.append(task) loop.run_until_complete(asyncio.wait(tasks))
16
CONCORRÊNCIA USANDO ASYNCIOimport time import asyncio import aiohttp from github import REPOS, ACCESS_TOKEN
async def get_repo_info(repo_url): async with aiohttp.ClientSession() as session: async with session.get(repo_url, params={'access_token': ACCESS_TOKEN}) response_data = await response.json() repo_info = { 'name': response_data['name'], 'full_name': response_data['full_name'], 'stargazers_count': response_data['stargazers_count' } print(repo_info)
17
AIO LIBShttps://github.com/aio-libs
https://github.com/python/asyncio/wiki/ThirdParty
18
PACOimport time import paco import aiohttp from github import REPOS, ACCESS_TOKEN
async def get_repo_info(repo_url): async with aiohttp.ClientSession() as session: async with session.get(repo_url, params={'access_token': ACCESS_TOKEN}) response_data = await response.json() repo_info = { 'name': response_data['name'], 'full_name': response_data['full_name'], 'stargazers_count': response_data['stargazers_count' } print(repo_info)
19
AIOHTTPfrom aiohttp import web
async def handle(request): return web.json_response({'message': 'Hello World'})
app = web.Application() app.router.add_get('/', handle) web.run_app(app, host='127.0.0.1', port=8080)
20
SANICfrom sanic import Sanic from sanic.response import json
app = Sanic()
@app.route('/') async def test(request): return json({'message': 'Hello World'})
if __name__ == '__main__': app.run(host='127.0.0.1', port=8080)
21
AIOREDISimport asyncio import aioredis
loop = asyncio.get_event_loop()
async def main(): redis = await aioredis.create_redis(('localhost', 6379), loop=loop) await redis.set('key', 'hello world') val = await redis.get('key') print(val) redis.close() await redis.wait_closed()
loop.run_until_complete(main())
22
AIOMCACHEimport asyncio import aiomcache
loop = asyncio.get_event_loop()
async def main(): mc = aiomcache.Client('127.0.0.1', 11211, loop=loop) await mc.set(b'key', b'hello world') value = await mc.get(b'key') print(value)
loop.run_until_complete(main())
23
AIOPGimport asyncio import aiopg from speakers import SPEAKERS
dsn = 'dbname=pythonday user=pythonday password=pythonday host=127.0.0.1'
async def get_pool(): return await aiopg.create_pool(dsn)
async def create_table(): pool = await get_pool() async with pool.acquire() as conn: async with conn.cursor() as cur: await cur.execute('DROP TABLE IF EXISTS speakers')
24
AIOPG SQLALCHEMYimport asyncio from aiopg.sa import create_engine import sqlalchemy as sa from speakers import SPEAKERS
metadata = sa.MetaData() speakers_table = sa.Table( 'speakers', metadata, sa.Column('id', sa.Integer, primary_key=True), sa.Column('name', sa.String(255)) )
async def get_engine(): return await create_engine(
25
PYTEST-ASYNCIOimport pytest import aiohttp from github import REPOS, ACCESS_TOKEN
async def get_repo_info(repo_url): async with aiohttp.ClientSession() as session: async with session.get(repo_url, params={'access_token': ACCESS_TOKEN}) response_data = await response.json() return { 'name': response_data['name'], 'full_name': response_data['full_name'], 'stargazers_count': response_data['stargazers_count' }
26