Я новичок в многопроцессорности python. Я пишу модуль redis pubsub, в котором издатель считывает данные из таблицы базы данных и публикует данные по каналу. На стороне подписчиков я намереваюсь создать ряд рабочих процессов, которые могут прослушивать канал, подписываясь на него, получать элемент из канала и выполнять некоторую операцию на нем. Я хочу остановить все процессы пула, когда любой процесс получает строку END
из канала. Для этого я использую multiprocessing.Manager().Queue()
для связи между пул-процессами. Мой абонентский модуль находится ниже:
import redis
import time
import traceback
import json
import multiprocessing as mp
import contextlib
NO_OF_PROCESS = 4
def newProcess(queue):
r = redis.StrictRedis()
p = r.pubsub()
p.subscribe('subChannel')
while True:
print ('Waiting...')
if (queue.get() == 'END'):
break
# Do some work from message
message = p.get_message()
print (message)
if message:
data = message['data']
# If 'END' received than stop all pool processes by setting a message in shared queue
if data == b'END':
queue.put('END')
break
else:
data = json.loads(data)
print (data)
time.sleep(1)
class Worker:
def __init__(self, NO_OF_PROCESS):
self.NO_OF_PROCESS = NO_OF_PROCESS
self.queue = mp.Manager().Queue()
self.pool = mp.Pool(processes = NO_OF_PROCESS)
def doWork(self):
[self.pool.apply(newProcess, args=(self.queue)) for i in range(self.NO_OF_PROCESS)]
def parallelExec():
worker = Worker(NO_OF_PROCESS)
worker.doWork()
parallelExec()
Проблема здесь в том, что я получаю следующую ошибку при попытке выполнить: TypeError: newProcess() argument after * must be an iterable, not AutoProxy[Queue]
. Пожалуйста, помогите, также если есть другой подход, чем хотелось бы услышать.
Вы не отправляете args как iterable, преобразовывая args в кортеж, добавляя запятую, чтобы решить проблему
[self.pool.apply(newProcess, args=(self.queue,)) for i in range(self.NO_OF_PROCESS)]