← Назад к вопросам
Как передать информацию между двумя процессами?
3.0 Senior🔥 131 комментариев
#Архитектура и паттерны#Асинхронность и многопоточность
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Как передать информацию между двумя процессами
В Python есть несколько способов передачи данных между процессами. Процессы имеют изолированную память, поэтому нужны специальные механизмы.
1. Queue (очередь) — самый популярный
import multiprocessing
from multiprocessing import Queue
def producer(queue):
"""Процесс, который отправляет данные"""
for i in range(5):
data = f"Message {i}"
queue.put(data) # Положить в очередь
print(f"Producer отправил: {data}")
def consumer(queue):
"""Процесс, который получает данные"""
while True:
data = queue.get() # Получить из очереди
if data is None: # Сигнал выхода
break
print(f"Consumer получил: {data}")
if __name__ == "__main__":
q = Queue()
p1 = multiprocessing.Process(target=producer, args=(q,))
p2 = multiprocessing.Process(target=consumer, args=(q,))
p1.start()
p2.start()
p1.join()
q.put(None) # Сигнал завершения
p2.join()
# Результат:
# Producer отправил: Message 0
# Consumer получил: Message 0
# Producer отправил: Message 1
# Consumer получил: Message 1
# ...
2. Pipe (труба) — двусторонний канал
import multiprocessing
from multiprocessing import Pipe
def parent_process(conn):
"""Родительский процесс"""
# Отправить данные
conn.send("Hello from parent")
# Получить ответ
message = conn.recv()
print(f"Parent получил: {message}")
conn.close()
def child_process(conn):
"""Дочерний процесс"""
# Получить данные
message = conn.recv()
print(f"Child получил: {message}")
# Отправить ответ
conn.send("Hello from child")
conn.close()
if __name__ == "__main__":
parent_conn, child_conn = Pipe()
p = multiprocessing.Process(target=child_process, args=(child_conn,))
p.start()
parent_process(parent_conn)
p.join()
# Результат:
# Child получил: Hello from parent
# Parent получил: Hello from child
3. Manager — общее состояние
Можно использовать общие структуры данных (dict, list):
import multiprocessing
from multiprocessing import Manager
def writer(shared_dict):
"""Процесс, который пишет в общий словарь"""
shared_dict["name"] = "John"
shared_dict["age"] = 30
shared_dict["scores"] = [10, 20, 30]
print("Writer записал данные")
def reader(shared_dict):
"""Процесс, который читает из общего словаря"""
# Подождать пока данные будут записаны
import time
time.sleep(1)
print(f"Reader прочитал: {shared_dict}")
print(f"Name: {shared_dict['name']}")
print(f"Scores: {shared_dict['scores']}")
if __name__ == "__main__":
with Manager() as manager:
shared_dict = manager.dict()
p1 = multiprocessing.Process(target=writer, args=(shared_dict,))
p2 = multiprocessing.Process(target=reader, args=(shared_dict,))
p1.start()
p2.start()
p1.join()
p2.join()
# Результат:
# Writer записал данные
# Reader прочитал: {'name': 'John', 'age': 30, 'scores': [10, 20, 30]}
4. Value и Array — для простых данных
import multiprocessing
from multiprocessing import Value, Array
def increment(counter, shared_array):
"""Увеличить счётчик и обновить массив"""
with counter.get_lock():
counter.value += 1
for i in range(len(shared_array)):
shared_array[i] = shared_array[i] * 2
if __name__ == "__main__":
# Общий счётчик (используем threading.Lock для синхронизации)
counter = Value('i', 0) # 'i' = int
# Общий массив
shared_array = Array('d', [1.0, 2.0, 3.0]) # 'd' = double
p = multiprocessing.Process(target=increment, args=(counter, shared_array))
p.start()
p.join()
print(f"Counter: {counter.value}") # 1
print(f"Array: {list(shared_array)}") # [2.0, 4.0, 6.0]
5. Socket (сокет) — для удалённых процессов
Если процессы на разных машинах:
import socket
import json
def server():
"""Сервер"""
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(("localhost", 5000))
sock.listen(1)
conn, addr = sock.accept()
print(f"Подключение от {addr}")
# Получить данные
data = conn.recv(1024).decode()
print(f"Получено: {data}")
# Отправить ответ
response = json.dumps({"status": "ok"})
conn.send(response.encode())
conn.close()
sock.close()
def client():
"""Клиент"""
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect(("localhost", 5000))
# Отправить данные
message = json.dumps({"message": "Hello"})
sock.send(message.encode())
# Получить ответ
response = sock.recv(1024).decode()
print(f"Ответ: {response}")
sock.close()
6. Pool — результаты из рабочих процессов
import multiprocessing
from multiprocessing import Pool
def square(x):
"""Вычислить квадрат"""
return x * x
if __name__ == "__main__":
with Pool(4) as pool:
# Отправить задачи в рабочие процессы
results = pool.map(square, [1, 2, 3, 4, 5])
print(results) # [1, 4, 9, 16, 25]
# Или использовать apply_async для асинхронного выполнения
async_result = pool.apply_async(square, (10,))
result = async_result.get() # Дождаться результата
print(result) # 100
Сравнение методов
Метод | Двусторонний | Синхронизация | Использование
─────────────────────────────────────────────────────────────
Queue | Нет | Нет | Передача данных
Pipe | Да | Нет | Диалог процессов
Manager | Да | Внутри | Общие структуры
Value/Array | Нет | Да (lock) | Простые данные
Socket | Да | Нет | Удалённые процессы
Pool | Нет | Нет | Параллелизм
Синхронизация между процессами
import multiprocessing
from multiprocessing import Lock, Semaphore
def worker(lock, counter_dict):
"""Безопасно работать со счётчиком"""
with lock:
counter_dict["count"] += 1
print(f"Count: {counter_dict['count']}")
if __name__ == "__main__":
with multiprocessing.Manager() as manager:
lock = Lock() # Мьютекс
counter = manager.dict({"count": 0})
processes = []
for _ in range(5):
p = multiprocessing.Process(target=worker, args=(lock, counter))
processes.append(p)
p.start()
for p in processes:
p.join()
print(f"Финальное значение: {counter['count']}") # 5
Рекомендации
- Queue — для передачи данных между процессами
- Pipe — для двусторонней коммуникации
- Manager.dict() — для общих структур данных
- Pool — для параллельных задач
- Socket — для удалённых процессов
Итог
Для передачи информации между процессами:
- Queue — простая и надёжная
- Pipe — для диалога
- Manager — для сложных структур
- Socket — для сетевого взаимодействия
- Всегда используй синхронизацию (locks) при совместном доступе к данным