Процессы, потоки и асинхронность в Python
Процесс
Допустим у нас есть программа Notepad. Когда мы запускаем Notepad, операционная система создает новый процесс notepad.exe и выделяет для него память. В этом процессе и выполняется вся программа Notepad.
В Python работает аналогично. Когда мы запускаем скрипт:
Copy codepython my_script.py
Создается отдельный процесс python.exe, выделяется память, и в нем начинает выполняться код скрипта my_script.py.
Пример с multiprocessing:
import threading def print_doc(doc_name): print(f"Printing {doc_name}") if __name__ == "__main__": thread1 = threading.Thread(target=print_doc, args=("doc1.txt",)) thread2 = threading.Thread(target=print_doc, args=("doc2.txt",)) thread1.start() thread2.start() thread1.join() thread2.join()
В этом примере мы импортируем модуль threading
и определяем функцию print_doc()
, которая представляет собой задачу, выполняемую в потоке. Затем мы создаем экземпляры класса Thread
, указывая функцию print_doc
в качестве цели, и запускаем потоки с помощью метода start()
. Метод join()
используется для ожидания завершения потоков.
Поток
Представим, что в Notepad мы можем одновременно открыть два документа - doc1.txt и doc2.txt. И печатать в них одновременно. Это будут два потока внутри одного процесса Notepad.
В Python мы можем создать несколько потоков в одном процессе:
pythonCopy codeimport threading def print_doc(doc_name): print(f"Printing {doc_name}") thread1 = threading.Thread(target=print_doc, args=("doc1.txt",)) thread2 = threading.Thread(target=print_doc, args=("doc2.txt",)) thread1.start() # запуск потока thread2.start()
Здесь в одном процессе Python запущено 2 потока, которые выполняются параллельно.
Асинхронность
Представим, что в Notepad мы можем начать печатать doc1.txt и не ждать окончания, а сразу же начать печатать doc2.txt. Это похоже на асинхронность в Python с async/await.
pythonCopy codeimport asyncio async def print_doc(doc_name): print(f"Start printing {doc_name}") await asyncio.sleep(1) # имитируем задержку print(f"Done printing {doc_name}") asyncio.run(print_doc("doc1.txt")) asyncio.run(print_doc("doc2.txt"))
Таким образом мы запускаем асинхронные задачи параллельно.
Django приложение
Классическое Django приложение работает в одном процессе и обрабатывает каждый запрос последовательно.
Чтобы сделать его асинхронным, нужно:
- Использовать async во views
- Настроить ASGI сервер, например Daphne
- Воспользоваться асинхронными библиотеками типа aiohttp
Это позволит ускорить обработку запросов за счет асинхронности.
А для масштабирования можно запустить несколько процессов через uWSGI/Gunicorn.