Pycon Ru 2014
http://2m.ahref.ws
Обзор некоторых выступлений, Mail.RU, Александр Емелин
Как не надо делать, чтобы ваш open-source продукт стал пользоваться успехом
Андрей Светлов, LevelUP
Документация на английском
ReadTheDocs
Тесты (95 %)
coverage.py
CI
Setup.py
Pypi
Обратная совместимость публичного API
_не _нужно _бояться _приватных _подчеркиваний
Если тяжело писать документацию
значит
API плохой
Пишите читаемый код
Pep8
Правильные имена (master-slave)
Понятные тесты
Многозадачность в Python и других языках
Андрей Власовских, JetBrains
Треды
~ 20 кб/тред, ограничение 2048 тредов
1 ядро из-за GIL, race conditions, блокирующий IO
Процессы
~ 10 мб/процесс, N ядер
Медленное общение между процессами
Кооперативный подход
~ 1 кб/dispatcher, 1 ядро, С10K
Erlang, Go
Share Memory By Communicating
Do Not Communicate Using Shared Memory
Asyncio
Твиттер-клиент на asyncio
с применением концепции акторов
Как писать для asyncio. Советы разработчика библиотеки
Андрей Светлов, LevelUP
PEP 3156
Пример
import json
import asyncio
import aiohttp
URL = 'http://p.corp.mail.ru/api/json'
@asyncio.coroutine
def get_free_parking_places():
response = yield from aiohttp.request('GET', URL)
body = yield from response.read_and_close()
return json.loads(body.decode())['places']
@asyncio.coroutine
def main():
result = yield from get_free_parking_places()
if __name__ == '__main__':
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
Обзор API
yield from
sleep
wait_for
call_soon
call_later
run_in_executor
gather
lock
queue
Явный loop
@coroutine
def sleep(delay, result=None, *, loop=None):
"""Coroutine that completes after a given time (in seconds)."""
future = futures.Future(loop=loop)
h = future._loop.call_later(delay, future.set_result, result)
try:
return (yield from future)
finally:
h.cancel()
Stream API
Не всегда нужно писать протоколы - есть Stream API
(High-level API)
@asyncio.coroutine
def print_http_headers(url):
url = urllib.parse.urlsplit(url)
reader, writer = yield from asyncio.open_connection(url.hostname, 80)
query = (
'HEAD {url.path} HTTP/1.0\r\n'
'Host: {url.hostname}\r\n'
'\r\n'
).format(url=url)
writer.write(query.encode('latin-1'))
while True:
line = yield from reader.readline()
if not line:
break
print(line.decode('latin1').rstrip())
Subprocess
Тоже есть High-level API
yield from asyncio.create_subprocess_shell(...)
yield from asyncio.create_subprocess_exec(...)
Подумали о путанице при создании Subprocess
(cmd - список или строка, когда shell=True или False)
Библиотеки
aiohttp
aiopg
aiozmq
aioredis в планах
Дебаг
import asyncio
@asyncio.coroutine
def test():
print("never scheduled")
test()
Решение
export PYTHONASYNCIODEBUG=1
(env) MacAir:env fz$ PYTHONASYNCIODEBUG=1 python test.py
Coroutine 'test' defined at test.py:3 was never yielded from
Дебаг, PDB
next, step работают корректно в PYTHON 3.4
Тестирование
class MyTest(unittest.TestCase): def setUp(self): self.loop = asyncio.new_event_loop() asyncio.set_event_loop(None) def tearDown(self): self.loop.close() def test_some_case():
@asyncio.coroutine def run(): yield from asyncio.sleep(0.5, loop=self.loop) self.loop.run_until_complete(run())
Trollius
yield From(f())
вместо
yield from f()
Библиотеки от asyncio на Trollius работать не будут и мало кто будет поддерживать 2 версии
Pycon Ru 2014
By Emelin Alexander
Pycon Ru 2014
- 831