Se ha denunciado esta presentación.
Utilizamos tu perfil de LinkedIn y tus datos de actividad para personalizar los anuncios y mostrarte publicidad más relevante. Puedes cambiar tus preferencias de publicidad en cualquier momento.

Андрей Светлов

Асинхронные сетевые приложения на Python. Вчера, сегодня и завтра

  • Inicia sesión para ver los comentarios

Андрей Светлов

  1. 1. АСИНХРОННЫЕ СЕТЕВЫЕ ПРИЛОЖЕНИЯ НА PYTHON ВЧЕРА, СЕГОДНЯ, ЗАВТРА АНДРЕЙ СВЕТЛОВ andrew.svetlov@gmail.com  @andrew_svetlov
  2. 2. О СЕБЕ Использую python 15+ лет Python Core Developer с 2012 Соавтор asyncio Главный разработчик aiohttp Дюжина библиотек в сообществе aio­libs
  3. 3. ОПРОС Кто использует Python 3? Разрабатывает WEB сайты на Django/Flask Понимает что такое асинхронное сетевое программирование Использует асинхронные frameworks (twisted/tornado/gevent)?
  4. 4. ЗАЧЕМ? 1,000 потоков OS 1,000,000 легковесных задач
  5. 5. Hynek Schlawack asyncio is another interesting topic. I was surprised how alive and well that little corner of the Python community is (albeit in mainly Russian speaking countries).
  6. 6. AIOHTTP ­­ АСИНХРОННЫЙ WEB Клиент Сервер Перманентные соединения Веб­сокеты
  7. 7. 3 ГОДА ИСТОРИИ Выделилися из asyncio (tulip) 21 releases 2800+ commits 100+ contributors
  8. 8. КЛИЕНТ
  9. 9. REQUESTS import requests r = requests.get('https://api.github.com/user', auth=('user', 'pass')) print(r.status_code) print(r.headers['content-type']) print(r.text)
  10. 10. AIOHTTP import aiohttp async def coro(): r = await aiohttp.get('https://api.github.com/user', auth=aiohttp.BasicAuth('user', 'pass')) print(r.status) print(r.headers['content-type']) print(await r.text()) r.close()
  11. 11. ПРАВИЛА ДЛЯ ASYNCIO 1. Корутина ­­ это async def 2. Вызывай корутину через await 3. Если функция содержит await ­­ сделай её корутиной async def func(): await asyncio.sleep(1)
  12. 12. REQUESTS С СЕССИЕЙ session = requests.Session() r = session.get(url)
  13. 13. AIOHTTP С СЕССИЕЙ session = aiohttp.ClientSession() async def coro(session): async with session.get(url) as r: print(r.status) print(await r.text())
  14. 14. ТАЙМАУТЫ async def coro(session): with aiohttp.Timeout(1.5): async with session.get(url) as r: ...
  15. 15. ВЕБ­СОКЕТЫ async with client.ws_connect( 'http://websocket-server.org/endpoint') as ws: async for msg in ws: if msg.data == 'close': await ws.close() break else: ws.send_str("Answer on " + msg.data)
  16. 16. СЕРВЕР
  17. 17. DJANGO from django.conf.urls import url from django.http import HttpResponse def index(request): return HttpResponse("Hello, world") urlpatterns = [ url(r'^$', index), ]
  18. 18. AIOHTTP from aiohttp import web async def handler(request): return web.Response(text="Hello, world") app = web.Application(loop=loop) app.router.add_route('GET', '/', handler) web.run_app(app)
  19. 19. TORNADO import tornado.ioloop import tornado.web class MainHandler(tornado.web.RequestHandler): def get(self): self.write("Hello, world") app = tornado.web.Application([ (r"/", MainHandler)]) app.listen(8888) tornado.ioloop.IOLoop.current().start()
  20. 20. ПОДКЛЮЧЕНИЕ БД import sqlalchemy as sa from aiopg.sa import create_engine metadata = sa.MetaData() tbl = sa.Table('tbl', metadata, sa.Column('id', sa.Integer, primary_key=True), sa.Column('val', sa.String(255))) app['db'] = await create_engine(...) async def close_db(app): app['db'].close() await app['db'].wait_closed() app.on_cleanup.append(close_db)
  21. 21. ЗАПРОСЫ В БД async def handler(request): txt = "" async with request.app['db'].acquire() as conn: await conn.execute(tbl.insert().values(val='abc')) async for row in conn.execute(tbl.select()): txt += "{}: {}n".format(row.id, row.val) return web.Response(text=txt)
  22. 22. СЕРВЕРНЫЕ ВЕБ­СОКЕТЫ async def handler(request): ws = web.WebSocketResponse() await ws.prepare(request) async for msg in ws: if msg.data == 'close': await ws.close() break else: ws.send_str(msg.data + '/answer') return ws
  23. 23. НЕТРИВИАЛЬНЫЕ ШТУЧКИ
  24. 24. ЖИЗНЕННЫЙ ЦИКЛ ЗАПРОСА­ОТВЕТА И MIDDLEWARES
  25. 25. СЕРВЕРНЫЕ СЕССИИ from aiohttp_session import get_session async def hander(request): session = await get_session(request) session['key'] = 'value' return web.Response()
  26. 26. DEBUG TOOLBAR
  27. 27. ASYNCIO ПОД КАПОТОМ
  28. 28. SELECTOR EVENT_READ/EVENT_WRITE register(fd, events, data=None) unregister(fd) select(timeout=None) select, poll, epoll, kqueue
  29. 29. EVENT LOOP add_reader(fd, callback, *args) remove_reader(fd) add_writer(fd, callback, *args) remove_writer(fd) ­­­ call_soon(callback, *args) call_later(delay, callback, *args)
  30. 30. ИТЕРАЦИЯ EVENT LOOP def run_forever(): while True: events = selector.select(timeout) for key, mask in events: if mask & EVENT_READ: key.reader(key.fileobj) if mask & EVENT_WRITE: key.writer(key.fileobj) for handler in ready: handler._run()
  31. 31. БУФЕРЫ СОКЕТА
  32. 32. ТАЙМЕРЫ
  33. 33. ПОЛЕЗНЫЕ СОВЕТЫ
  34. 34. ЦИКЛ РАЗРАБОТКИ Для разработки ­­ один процесс Удобство запуска тестов Разворачивать на отдельных процессах­контейнерах­узлах
  35. 35. PYTHONASYNCIODEBUG=1 async def f(): fut = asyncio.Future() fut.set_exception(RuntimeError()) del fut ... ERROR:asyncio:Future exception was never retrieved future: Future finished exception=RuntimeError() RuntimeError
  36. 36. $ PYTHONASYNCIODEBUG=x python myapp.py ERROR:asyncio:Future exception was never retrieved future: Future finished exception=RuntimeError() created at filename.py:10 source_traceback: Object created at (most recent call last): ... File "filename.py", line 10, in f fut = asyncio.Future() RuntimeError
  37. 37. EXPLICIT LOOP def request(method, url, *, loop=None): ... loop = asyncio.get_event_loop() await request('GET', 'http://python.org', loop=loop)
  38. 38. ТЕСТИРОВАНИЕ class Test(unittest.TestCase): def setUp(self): self.loop = asyncio.new_event_loop() asyncio.set_event_loop(None) def tearDown(self): self.loop.close() def test_func(self): async def go(): self.assertEqual(1, await func(loop=loop)) self.loop.run_until_complete(go())
  39. 39. ПРОИЗВОДИТЕЛЬНОСТЬ Как у Tornado или Twisted Достаточно неплохо для highload Выдерживает миллионы online пользователей и пр.
  40. 40. ВОПРОСЫ? АНДРЕЙ СВЕТЛОВ andrew.svetlov@gmail.com @andrew_svetlov

×