← Назад к вопросам
Зачем нужен процесс?
1.6 Junior🔥 71 комментариев
#Python Core#Асинхронность и многопоточность
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Зачем нужен процесс в программировании
Процесс — это независимый экземпляр программы, работающий со своим собственным адресным пространством, памятью и ресурсами. Это фундаментальная единица выполнения программ в операционной системе.
Что такое процесс
Процесс содержит:
- Код программы (исполняемый файл)
- Свою память (heap, stack, data segment)
- Файловые дескрипторы (открытые файлы, сокеты)
- Переменные окружения
- PID (Process ID) — уникальный идентификатор
import os
import sys
print(f"Текущий PID: {os.getpid()}")
print(f"Parent PID: {os.getppid()}")
print(f"Имя процесса: {sys.argv[0]}")
print(f"Память процесса: ~{os.getpid()} байт")
1. Разделение ресурсов между независимыми программами
import os
from multiprocessing import Process
def worker(name, count):
"""Независимый процесс со своей памятью"""
print(f"Worker {name} started (PID: {os.getpid()})")
for i in range(count):
print(f"Worker {name}: iteration {i}")
print(f"Worker {name} finished")
if __name__ == '__main__':
# Создать несколько независимых процессов
p1 = Process(target=worker, args=("A", 3))
p2 = Process(target=worker, args=("B", 3))
print(f"Main process PID: {os.getpid()}")
p1.start()
p2.start()
p1.join()
p2.join()
print("All processes finished")
# Каждый процесс имеет свой PID и независимую память
2. Настоящий параллелизм (Multiprocessing)
В отличие от потоков, процессы работают параллельно на многоядерных системах:
import time
from multiprocessing import Process
import os
def cpu_intensive(n):
"""CPU-bound операция"""
total = 0
for i in range(n):
total += i
return total
def sequential_execution():
"""Последовательное выполнение"""
start = time.time()
cpu_intensive(100000000)
cpu_intensive(100000000)
print(f"Sequential: {time.time() - start:.2f}s")
def parallel_execution():
"""Параллельное выполнение в процессах"""
start = time.time()
p1 = Process(target=cpu_intensive, args=(100000000,))
p2 = Process(target=cpu_intensive, args=(100000000,))
p1.start()
p2.start()
p1.join()
p2.join()
print(f"Parallel: {time.time() - start:.2f}s")
if __name__ == '__main__':
sequential_execution() # ~2.5 сек
parallel_execution() # ~1.3 сек (на 2 ядрах)
3. Изоляция и безопасность
Каждый процесс имеет собственное адресное пространство:
from multiprocessing import Process
global_var = 10 # Глобальная переменная в главном процессе
def modify_global():
global global_var
global_var = 20 # Изменит только в этом процессе
print(f"В процессе: global_var = {global_var}")
if __name__ == '__main__':
print(f"До: global_var = {global_var}")
p = Process(target=modify_global)
p.start()
p.join()
print(f"После: global_var = {global_var}")
# Вывод: После: global_var = 10 (не изменилась!)
Это гарантирует изоляцию (важно для безопасности):
from multiprocessing import Process
import traceback
def crashing_process():
raise Exception("Crash in worker process")
if __name__ == '__main__':
try:
p = Process(target=crashing_process)
p.start()
p.join()
# Главный процесс не падает!
print("Main process still alive")
except Exception as e:
print(f"Caught: {e}")
traceback.print_exc()
4. Использование Process Pool для масштабирования
from multiprocessing import Pool
import time
def process_item(item):
"""Обработать один элемент"""
time.sleep(1) # Имитация работы
return item ** 2
if __name__ == '__main__':
items = list(range(10))
# Последовательно
start = time.time()
results = [process_item(i) for i in items]
print(f"Sequential: {time.time() - start:.2f}s")
# Параллельно на 4 процессах
start = time.time()
with Pool(4) as pool:
results = pool.map(process_item, items)
print(f"Parallel (4 processes): {time.time() - start:.2f}s")
print(f"Results: {results}")
5. Обработка больших объёмов данных
from multiprocessing import Pool
import os
def process_file_chunk(chunk_info):
"""Обработать часть файла в отдельном процессе"""
file_path, start, end = chunk_info
chunk_data = []
with open(file_path, 'r') as f:
f.seek(start)
chunk = f.read(end - start)
chunk_data = chunk.strip().split('\n')
# Обработка
processed = [line.upper() for line in chunk_data]
return len(processed)
def process_large_file(file_path, num_processes=4):
"""Обработать большой файл параллельно"""
file_size = os.path.getsize(file_path)
chunk_size = file_size // num_processes
chunks = [
(file_path, i * chunk_size, (i + 1) * chunk_size)
for i in range(num_processes)
]
with Pool(num_processes) as pool:
results = pool.map(process_file_chunk, chunks)
return sum(results)
if __name__ == '__main__':
# total_lines = process_large_file('large_file.txt')
# print(f"Processed {total_lines} lines")
pass
6. Долгоживущие фоновые процессы
from multiprocessing import Process
import time
import signal
def background_worker():
"""Фоновый процесс, работающий независимо"""
try:
while True:
print("Background worker is running...")
time.sleep(2)
except KeyboardInterrupt:
print("Background worker stopped")
if __name__ == '__main__':
# Запустить фоновый процесс
worker_process = Process(target=background_worker, daemon=True)
worker_process.start()
# Основная программа продолжает работу
for i in range(5):
print(f"Main process: {i}")
time.sleep(1)
print("Main process finished")
# Daemon процесс автоматически завершится
7. Коммуникация между процессами (IPC)
from multiprocessing import Process, Queue, Pipe
# Использование Queue
def producer(queue):
for i in range(5):
queue.put(f"Item {i}")
print(f"Produced: Item {i}")
def consumer(queue):
while True:
try:
item = queue.get(timeout=1)
print(f"Consumed: {item}")
except:
break
if __name__ == '__main__':
q = Queue()
p1 = Process(target=producer, args=(q,))
p2 = Process(target=consumer, args=(q,))
p1.start()
p2.start()
p1.join()
p2.join()
# Использование Pipe
def sender(conn):
for i in range(3):
conn.send(f"Message {i}")
conn.close()
def receiver(conn):
while True:
try:
msg = conn.recv()
print(f"Received: {msg}")
except EOFError:
break
if __name__ == '__main__':
parent_conn, child_conn = Pipe()
p1 = Process(target=sender, args=(child_conn,))
p2 = Process(target=receiver, args=(parent_conn,))
p1.start()
p2.start()
p1.join()
p2.join()
8. Когда использовать процессы
Процессы используют для:
- CPU-bound операции (вычисления, обработка данных)
- Параллельная работа на многоядерных системах
- Долгоживущие фоновые задачи
- Разделение работы между независимыми компонентами
- Обработка больших файлов параллельно
- Высокая надёжность (крах одного процесса не влияет на другие)
Процессы НЕ используют для:
- I/O операции (используй async или threading)
- Частое создание процессов (дорого)
- Нужна частая общая память (используй threading или asyncio)
9. Сравнение: Process vs Thread vs Async
| Аспект | Process | Thread | Async |
|---|---|---|---|
| Параллелизм | Настоящий | Псевдопараллелизм | Конкурентный |
| GIL | Нет | Да (ограничение) | Нет |
| Память | ~50МБ | ~2МБ | ~1KB |
| CPU-bound | Отлично | Плохо | Плохо |
| I/O bound | OK | OK | Отлично |
| Изоляция | Полная | Частичная | Полная |
| Сложность | Высокая | Средняя | Средняя |
Заключение
Процесс — это изолированный экземпляр программы с собственной памятью и ресурсами. Процессы необходимы для:
- Настоящего параллелизма на многоядерных системах
- CPU-bound операций
- Высокой надёжности и изоляции
- Долгоживущих фоновых задач
Основной недостаток — высокое потребление памяти и затраты на создание, поэтому для I/O операций лучше использовать async или threading.