- ru
- Language: en
- Documentation version: latest
Процессы и потоки в Python (CPython)
Для начала нам нужно разобраться с терминами:
процесс (process) - это, грубо говоря, запущенная программа. Процессу выделяются отдельные ресурсы: память, процессорное время
поток (thread) - это единица исполнения в процессе. Потоки разделяют ресурсы процесса, к которому они относятся.
Python (а точнее, CPython - реализация, которая используется в книге) оптимизирован для работы в однопоточном режиме. Это хорошо, если в программе используется только один поток. И, в то же время, у Python есть определенные нюансы работы в многопоточном режиме. Связаны они с тем, что CPython использует GIL (global interpreter lock).
GIL не дает нескольким потокам исполнять одновременно код Python. Если не вдаваться в подробности, то GIL можно представить как некий переходящий флаг, который разрешает потокам выполняться. У кого флаг, тот может выполнять работу. Флаг передается либо каждые сколько-то инструкций Python, либо, например, когда выполняются какие-то операции ввода-вывода.
Поэтому получается, что разные потоки не будут выполняться параллельно, а программа просто будет между ними переключаться, выполняя их в разное время. Однако, если в программе есть некое “ожидание”: пакетов из сети, запроса пользователя, пауза типа time.sleep, то в такой программе потоки будут выполняться как будто параллельно. А всё потому, что во время таких пауз флаг (GIL) можно передать другому потоку.
То есть, потоки отлично подходят для задач, которые связаны с операциями ввода-вывода:
Подключение к оборудованию и подключение по сети в целом
Работа с файловой системой
Скачивание файлов по сети
Note
В интернете часто можно встретить выражения “В Python лучше вообще не использовать потоки”. К сожалению, такие фразы не всегда пишут с контекстом, а именно, что речь о конкретных задачах, которые завязаны на CPU.
В следующих разделах рассматривается, как использовать потоки для подключения по Telnet/SSH. И проверяется, какое суммарное время будет занимать исполнение скрипта, по сравнению с последовательным исполнением и с использованием процессов.
Процессы
Процессы позволяют выполнять задачи на разных ядрах компьютера. Это важно для задач, которые завязаны на CPU. Для каждого процесса создается своя копия ресурсов, выделяется память, у каждого процесса свой GIL. Это же делает процессы более тяжеловесными, по сравнению с потоками.
Кроме того, количество процессов, которые запускаются параллельно, зависит от количества ядер и CPU и обычно исчисляется в десятках, тогда как количество потоков для операций ввода-вывода может исчисляться в сотнях.
Процессы и потоки можно совмещать, но это усложняет программу и на базовом уровне для операций ввода-вывода лучше остановиться на потоках.
Note
Совмещение потоков и процессов, то есть запуск процесса в программе и внутри него уже запуск потоков - сильно усложняет траблшутинг программы. И лучше такой вариант не использовать.
Несмотря на то, что, как правило, для задач ввода-вывода лучше использовать потоки с некоторыми модулями надо использовать процессы, так как они могут некорректно работать с потоками.
Note
Помимо процессов и потоков есть еще один вариант одновременного подключения к оборудованию: асинхронное программирование. Этот вариант не рассматривается в книге.