Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Асинхронщина в Python

Асинхронщина в Python

Александр Полищук (ООО "Код безопасности") @ Moscow Python Meetup 52
"Python – это замечательный язык программирования, но есть одна вещь, которая ограничивает нашу свободу творчества, и называется она GIL. Спикер расскажет, как можно с ним договориться и не ограничивать себя одним потоком".
Видео: http://www.moscowpython.ru/meetup/52/asyncronous-python/

Moscow Python Meetup

January 24, 2018
Tweet

More Decks by Moscow Python Meetup

Other Decks in Programming

Transcript

  1. Как можно делать одновременно несколько вещей в Python • Отдельные

    процессы • Отдельные потоки • Асинхронный код
  2. Отдельные процессы это хорошо • Отдельные программы • Изолированы •

    Работают параллельно • Используют все ресурсы процессора
  3. Отдельные процессы это плохо • Нет разделяемых переменных • Необходима

    синхронизация • Очень затратные • Зависят от количества ядер
  4. Пример from multiprocessing import Pool def print_word(word): print(word) If __name__

    == "__main__": pool = Pool() pool.map(print_word, ["Hello", "MoscowPython", "Meetup"]) pool.close() pool.join()
  5. Пример из жизни import os from PIL import Image from

    multiprocessing import Pool def create_thumbnail(filename): im = Image.open(filename) im.thumbnail((75, 75), Image.ANTIALIAS) save_path = os.path.join(".", "thumbnails", fname) im.save(save_path) if __name__ == "__main__": images = [file for file in os.listdir(".") if "jpeg" in file] pool = Pool() pool.map(create_thumbnail, images) pool.close() pool.join()
  6. Отдельные потоки это хорошо • Общая память • Общие глобальные

    переменные • Не требуют больших ресурсов
  7. Отдельные потоки это хорошо • Общая память • Общие глобальные

    переменные • Не требуют больших ресурсов • Отлично подходит для I/O-bound операций
  8. Отдельные потоки это плохо • GIL • Нельзя использовать CPU-bound

    функции • Код не тривиален • Одновременный доступ к памяти
  9. Пример import threading def worker(num): """thread worker function""" print 'Worker:

    %s' % num return threads = [] for i in range(5): t = threading.Thread(target=worker, args=(i,)) threads.append(t) t.start()
  10. Пример из жизни import threading, requests def pinger(url): return requests.get(url)

    e1 = threading.Event(); e2 = threading.Event() t1 = threading.Thread(target=pinger, args=('https://yandex.ru',)) t2 = threading.Thread(target=pinger, args=('https://mail.ru',)) t1.start(); t2.start() e1.set() t1.join(); t2.join()
  11. Асинхронный код это хорошо • Выполнение в одном процессе и

    потоке • Очень малое использование ресурсов системы
  12. Асинхронный код это хорошо • Выполнение в одном процессе и

    потоке • Очень малое использование ресурсов системы • ОС независим
  13. Асинхронный код это плохо • Сложность отладки • Трудно понять,

    в каком контексте мы находимся • Сложночитаемый код
  14. Асинхронный код это плохо • Сложность отладки • Трудно понять,

    в каком контексте мы находимся • Сложночитаемый код • «Очень легко выстрелить себе в ногу» (с)
  15. Пример import asyncio async def hello_world(): print("Hello Meetup!") loop =

    asyncio.get_event_loop() loop.run_until_complete(hello_world()) loop.close()
  16. Пример из жизни import requests import asyncio async def ping_url(url):

    return requests.get(url) loop = asyncio.get_event_loop() tasks = [ping_url('https://yandex.ru'), ping_url('https://mail.ru')] loop.run_until_complete(asyncio.wait(tasks)) loop.close()
  17. Итоги • Работают «параллельно» • Использует одно ядро • Максимум

    несколько сотен Multiprocessing Threading • Работают параллельно • Использует все ядра • Максимум пара десятков
  18. Итоги Async • Работают «параллельно» • Использует одно ядро •

    Максимум несколько сотен Multiprocessing Threading • Работают конкурентно • Использует одно ядро и один поток • Тысячи • Работают параллельно • Использует все ядра • Максимум пара десятков