Многопроцессорный процесс запускается непосредственно при создании

Привет, у меня проблема с многопроцессорностью в python 3.7. Я сделал прослушиватель, который должен ждать ответа от сервера, не блокируя остальную часть программы (асинхронная связь):

self = cl.appendSend('bar', base_list)
print("client erstellt neuen nebenläufigen listener, für die Antwort des Servers")
multiprocessing.set_start_method("spawn")
queue = multiprocessing.Queue()
process = multiprocessing.Process(target = cl.appendResponse(), args=(self))
process.start()
print("listener aktiv")

thread = threading.Thread(target= waitingPrinter(), args=(process, queue))
print(thread)

здесь все начинается но строка process = multiprocessing.Process(target = cl.appendResponse(), args=(self)) запускается один раз, проходит, а затем, после завершения, просто запускается снова. Отладчик никогда не покидает эту строку.

Метод, запускаемый в процессе:

 def appendResponse(self):
        print("nebenläufiger listener aktiv")
        msgrcv = self.chan.receive_from(self.server)
        print("nebenläufiger listener hat Antwort erhalten")
        return msgrcv  # pass it to caller

К сожалению, из-за авторских прав я не могу опубликовать больше, но метод работает нормально в первый раз и терпит неудачу во второй раз с сообщением: Traceback (последний последний вызов):

> File "D:/Verteile Systeme 2/neues Lab/git/vs2lab/lab2/rpc/runcl.py",
> line 27, in <module>
>     process = multiprocessing.Process(target = cl.appendResponse(), args=(self))   File "C:\Program Files
> (x86)\Python37-32\lib\multiprocessing\process.py", line 82, in
> __init__
>     self._args = tuple(args) TypeError: 'Client' object is not iterable

Поэтому мне интересно, почему процесс с cl.appendResponse() даже запускается при привязке к процессу и не ждет process.start(), а если уже не в ответе на это, то почему он тогда запускается напрямую второй раз. И конечно, как я могу это исправить.

Также есть ли способ заменить обработку потоком и по-прежнему получать возвращаемое значение? У меня много проблем с обработкой и возвратом значений.

Анализ настроения постов в Twitter с помощью Python, Tweepy и Flair
Анализ настроения постов в Twitter с помощью Python, Tweepy и Flair
Анализ настроения текстовых сообщений может быть настолько сложным или простым, насколько вы его сделаете. Как и в любом ML-проекте, вы можете выбрать...
7 лайфхаков для начинающих Python-программистов
7 лайфхаков для начинающих Python-программистов
В этой статье мы расскажем о хитростях и советах по Python, которые должны быть известны разработчику Python.
Установка Apache Cassandra на Mac OS
Установка Apache Cassandra на Mac OS
Это краткое руководство по установке Apache Cassandra.
Сертификатная программа "Кванты Python": Бэктестер ансамблевых методов на основе ООП
Сертификатная программа "Кванты Python": Бэктестер ансамблевых методов на основе ООП
В одном из недавних постов я рассказал о том, как я использую навыки количественных исследований, которые я совершенствую в рамках программы TPQ...
Создание персонального файлового хранилища
Создание персонального файлового хранилища
Вы когда-нибудь хотели поделиться с кем-то файлом, но он содержал конфиденциальную информацию? Многие думают, что электронная почта безопасна, но это...
Создание приборной панели для анализа данных на GCP - часть I
Создание приборной панели для анализа данных на GCP - часть I
Недавно я столкнулся с интересной бизнес-задачей - визуализацией сбоев в цепочке поставок лекарств, которую могут просматривать врачи и...
0
0
123
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

target = cl.appendResponse() запустит функцию и вернет результат цели. Правильным синтаксисом будет target=cl.appendResponse, который сообщит процессу запустить cl.appendResponse при запуске().

Ответ принят как подходящий

Причина кажущегося немедленного выполнения процесса была правильно указана philipp в их отвечать.
Аргумент target для Process принимает вызываемый объект, который должен вызываться методом run(). Ваш код передает все, что возвращает self.chan.receive_from(self.server).
В строке process = multiprocessing.Process(target = cl.appendResponse(), args=(self)) нет запущенного подпроцесса. Ваш метод запускается в основном процессе и блокирует его. На заметку: у вас будет точно такая же проблема с вашим thread по той же причине: thread = threading.Thread(target= waitingPrinter(), args=(process, queue))

После того, как ваш метод завершил выполнение в основном процессе, инициализация вашего объекта процесса вызывает TypeError внутри метода __init__ класса BaseProcess.
Вы передаете аргумент self своему процессу, но делаете это неправильно. Аргумент args требует кортежа аргументов. Создание кортежа с помощью литерала требует запятой в конце, если указано только одно значение: args=(self,). Ваш код эффективно передает self, то есть объект Client напрямую, который не является итерируемым и, следовательно, вызывает ошибку.
В вашем случае appendResponse кажется связанным методом объекта Client. Он получит аргумент self через внутреннюю работу системы классов Python. Явная передача его через процесс вызовет еще один TypeError за передачу двух позиционных аргументов методу, который принимает только один. Если appendSend не возвращает что-то другое, кроме экземпляра Clientcl, для которого вы его вызываете, отбросьте параметр args в инстанцировании процесса.

С другой стороны, обратите внимание: метод запуска spawn является единственным доступным в Windows и, следовательно, используется по умолчанию. Если ваш код не должен запускаться под Unix с использованием этого метода запуска, эта строка избыточна: multiprocessing.set_start_method("spawn")

Спасибо, хорошо знать, что не так, а также то, что я неправильно отправил аргументы. Я изменил его и попробую завтра, когда снова смогу связаться с сервером. Поскольку вы, кажется, понимаете работу python лучше, чем я, мне интересно, что вы думаете о моей конструкции, что поток получает ответ процесса, а затем распечатывает его. Мое предположение состоит в том, что поток будет запущен и ничего не делает, поскольку остальная часть программы продолжает работать и запускается только тогда, когда процесс возвращает ответ. Я прав с этим предположением?

Etaila 22.05.2019 19:27

@Etaila Это немного сложно сказать, так как я не знаю, что происходит в waitingPrinter, но, насколько я понимаю из вашего описания, ваше предположение кажется правильным. Однако, поскольку кажется, что ваш процесс просто ожидает каких-то данных с сервера, почему бы не отказаться от него совсем и не делать все в потоке? Задача процесса, похоже, связана с вводом-выводом, поэтому глобальная блокировка интерпретатора Python не должна быть проблемой. Когда вы передаете свой объект Client непосредственно в waitingPrinter, вы можете вызвать метод внутри него и напрямую обработать результат после его получения.

shmee 22.05.2019 19:45

@shmee Ожидающийпринтер просто использует process.join и 'print()', чтобы написать ответ в консоли и ничего более. И причина, по которой я разделил эти два, заключается в том, что процесс исходит из другого класса, который обрабатывает только связь с сервером, печать результата или в реальной задаче, дальнейшая обработка ответа — это другой класс, где ожидающийпринтер определяется в. И я не чувствую себя комфортно, в основном отказываясь от клиента в контексте задачи. Если бы это был частный проект, я, вероятно, сделал бы все в процессе.

Etaila 22.05.2019 19:57

@Etaila О, и теперь, когда я присмотрелся еще ближе, вам не нужно передавать этот аргумент при создании экземпляра вашего процесса. На самом деле, он поднимет еще один TypeError, когда будет вызван process.start(). appendResponse кажется связанным методом вашего объекта Client, поэтому он будет передан как таковой. Он получит экземпляр, указанный в self, внутри. Повторная передача self приведет к тому, что метод будет вызываться с двумя позиционными аргументами, в то время как он принимает только один.

shmee 22.05.2019 20:05

Другие вопросы по теме