← Назад к вопросам

Создается ли поток самим Python

2.0 Middle🔥 161 комментариев
#Python Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Создание потоков в 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.