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/

Avatar for Moscow Python Meetup

Moscow Python Meetup PRO

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 • Работают конкурентно • Использует одно ядро и один поток • Тысячи • Работают параллельно • Использует все ядра • Максимум пара десятков