Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Создание потоков в Python
Поток (thread) не создается самим Python автоматически. В Python есть главный поток, который запускается интерпретатором, но дополнительные потоки должны создаваться явно программистом.
Главный поток
Когда вы запускаете Python скрипт, интерпретатор создаёт один главный поток (main thread), в котором выполняется весь код:
import threading
print(f"Current thread: {threading.current_thread().name}")
# Output: Current thread: MainThread
Создание дополнительных потоков
Для создания новых потоков используется модуль threading:
import threading
import time
def worker(name):
print(f"Worker {name} started")
time.sleep(1)
print(f"Worker {name} finished")
# Создаём новый поток
thread1 = threading.Thread(target=worker, args=("A",))
thread1.start() # Запускаем поток
# Ждём завершения
thread1.join()
print("Main thread continues")
GIL (Global Interpreter Lock)
Важное ограничение в CPython — GIL (Global Interpreter Lock). Даже если создано несколько потоков, только один может выполнять код Python одновременно:
import threading
import time
def cpu_bound_task():
total = 0
for i in range(50_000_000):
total += i
# Однопоточное выполнение
start = time.time()
cpu_bound_task()
cpu_bound_task()
print(f"Sequential: {time.time() - start:.2f}s")
# Многопоточное выполнение (медленнее!)
start = time.time()
t1 = threading.Thread(target=cpu_bound_task)
t2 = threading.Thread(target=cpu_bound_task)
t1.start()
t2.start()
t1.join()
t2.join()
print(f"Threading: {time.time() - start:.2f}s")
Многопоточность медленнее из-за overhead контекстного переключения!
Когда потоки полезны
Потоки эффективны для I/O-bound операций (сетевые запросы, файлы):
import threading
import requests
def fetch_url(url):
response = requests.get(url)
print(f"Fetched {len(response.text)} bytes from {url}")
threads = []
urls = ["https://example.com", "https://google.com", "https://github.com"]
for url in urls:
t = threading.Thread(target=fetch_url, args=(url,))
threads.append(t)
t.start()
for t in threads:
t.join()
print("All URLs fetched")
Альтернативы потокам
Для современного Python есть лучшие подходы:
1. asyncio — асинхронное программирование
import asyncio
async def fetch_url(url):
print(f"Fetching {url}")
await asyncio.sleep(1) # Имитация сетевого запроса
print(f"Done {url}")
async def main():
await asyncio.gather(
fetch_url("url1"),
fetch_url("url2"),
fetch_url("url3"),
)
asyncio.run(main())
2. multiprocessing — для CPU-bound задач
from multiprocessing import Process
def cpu_task():
total = sum(range(50_000_000))
return total
if __name__ == "__main__":
p1 = Process(target=cpu_task)
p2 = Process(target=cpu_task)
p1.start()
p2.start()
p1.join()
p2.join()
print("Done")
Жизненный цикл потока
import threading
def worker():
print("Работаю...")
t = threading.Thread(target=worker, daemon=False)
print(f"Alive: {t.is_alive()}") # False (не запущен)
t.start()
print(f"Alive: {t.is_alive()}") # True (выполняется)
t.join() # Ждём завершения
print(f"Alive: {t.is_alive()}") # False (завершён)
Демон потоки
Демон потоки завершаются автоматически при завершении главного потока:
import threading
import time
def daemon_task():
for i in range(10):
print(f"Daemon {i}")
time.sleep(0.5)
t = threading.Thread(target=daemon_task, daemon=True)
t.start()
time.sleep(1)
print("Main thread ending")
# Демон поток будет убит, даже если не завершился
Заключение
Python не создает потоки автоматически. Разработчик должен явно использовать threading.Thread() для создания новых потоков. Однако из-за GIL потоки неэффективны для CPU-bound задач. Для современного асинхронного кода лучше использовать asyncio, а для параллелизма — multiprocessing.