Какие знаешь способо передачи данных между процессами в Python?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Способы передачи данных между процессами в Python
Межпроцессная коммуникация (IPC) — критически важна для многопроцессных приложений. Python предоставляет несколько мощных инструментов для этого.
1. Queue из multiprocessing
Queue — это потокобезопасная очередь для передачи данных между процессами. Это наиболее простой и рекомендуемый способ.
from multiprocessing import Process, Queue
import time
def worker(queue):
for i in range(3):
queue.put(f"Message {i}")
time.sleep(1)
def main():
q = Queue()
p = Process(target=worker, args=(q,))
p.start()
while True:
try:
data = q.get(timeout=2)
print(f"Получено: {data}")
except:
break
p.join()
if __name__ == '__main__':
main()
Преимущества: простота, безопасность, поддержка различных типов данных. Недостатки: синхронная природа (блокирующие операции).
2. Pipe
Pipe — это двусторонний канал связи между двумя процессами. Меньше overhead чем Queue, но работает только с двумя процессами.
from multiprocessing import Process, Pipe
def worker(conn):
conn.send("Hello from child")
msg = conn.recv()
print(f"Child получил: {msg}")
conn.close()
def main():
parent_conn, child_conn = Pipe()
p = Process(target=worker, args=(child_conn,))
p.start()
msg = parent_conn.recv()
print(f"Parent получил: {msg}")
parent_conn.send("Hello from parent")
p.join()
if __name__ == '__main__':
main()
Преимущества: низкий overhead, скорость. Недостатки: работает только с двумя процессами.
3. Shared Memory
Shared Memory — прямой доступ к общей памяти. Самый быстрый способ, но требует тщательной синхронизации.
from multiprocessing import Process, Value, Array, Lock
import time
def worker(shared_int, shared_array, lock):
for i in range(5):
with lock:
shared_int.value += 1
shared_array[i] = i * 10
time.sleep(0.1)
def main():
shared_int = Value('i', 0)
shared_array = Array('d', 5)
lock = Lock()
processes = []
for _ in range(3):
p = Process(target=worker, args=(shared_int, shared_array, lock))
p.start()
processes.append(p)
for p in processes:
p.join()
print(f"Финальное значение: {shared_int.value}")
if __name__ == '__main__':
main()
Преимущества: максимальная скорость. Недостатки: требует явной синхронизации, сложнее в отладке.
4. Manager
Manager — высокоуровневая абстракция для совместного использования данных. Позволяет использовать сложные структуры данных.
from multiprocessing import Process, Manager
def worker(shared_dict, shared_list):
shared_dict['key'] = 'value from child'
shared_list.append('item from child')
def main():
with Manager() as manager:
shared_dict = manager.dict()
shared_list = manager.list()
p = Process(target=worker, args=(shared_dict, shared_list))
p.start()
p.join()
print(f"Словарь: {dict(shared_dict)}")
if __name__ == '__main__':
main()
Преимущества: поддержка сложных типов, простота. Недостатки: медленнее чем Shared Memory.
5. Redis и внешние хранилища
Для распределённых систем можно использовать внешние хранилища как промежуточный слой.
import redis
from multiprocessing import Process
def worker(worker_id):
r = redis.Redis()
for i in range(3):
r.lpush(f'queue:{worker_id}', f'message {i}')
def main():
r = redis.Redis()
processes = []
for i in range(2):
p = Process(target=worker, args=(i,))
p.start()
processes.append(p)
for p in processes:
p.join()
Преимущества: масштабируемость, независимость процессов. Недостатки: требует отдельного сервиса.
6. Файлы и файловые блокировки
Для простых случаев можно использовать файловую систему.
import json
import fcntl
def write_data(filename, data):
with open(filename, 'w') as f:
fcntl.flock(f.fileno(), fcntl.LOCK_EX)
try:
json.dump(data, f)
finally:
fcntl.flock(f.fileno(), fcntl.LOCK_UN)
Преимущества: простота, нет зависимостей. Недостатки: медленно, требует тщательного управления.
Рекомендации
- Queue: начните отсюда, 90% случаев
- Pipe: когда два процесса и нужна скорость
- Shared Memory: только при критичных требованиях к производительности
- Manager: для быстрого прототипирования
- Redis: для распределённых систем и микросервисов