Как видно из приведенного ниже кода, две многопроцессорные обработки выполняются вместе, но у обеих есть момент, который может запросить input()
в Терминале. Есть ли способ приостановить другую многопроцессорную обработку, пока в Терминале не будет дан ответ?
Файл Code_One
архаичный и простой пример для ускорения объяснения:
from time import sleep
def main():
sleep(1)
print('run')
sleep(1)
print('run')
sleep(1)
input('Please, give the number:')
Файл Code_Two
архаичный и простой пример для ускорения объяснения:
from time import sleep
def main():
sleep(2)
input('Please, give the number:')
sleep(1)
print('run 2')
sleep(1)
print('run 2')
sleep(1)
print('run 2')
sleep(1)
print('run 2')
sleep(1)
print('run 2')
Файл Main_Code
:
import Code_One
import Code_Two
import multiprocessing
from time import sleep
def main():
while True:
pression = multiprocessing.Process(target=Code_One.main)
xgoals = multiprocessing.Process(target=Code_Two.main)
pression.start()
xgoals.start()
pression.join()
xgoals.join()
print('Done')
sleep(5)
if __name__ == '__main__':
main()
Как мне поступить в этой ситуации?
В этом примере, поскольку он не приостанавливает другой мульти, всякий раз, когда он запрашивает ввод, возникает эта ошибка:
input('Please, give the number:')
EOFError: EOF when reading a line
Конечно, это возможно. Для этого вам нужно будет использовать какой-то механизм межпроцессного взаимодействия (IPC), чтобы позволить двум процессам координировать свои действия. time.sleep
— не лучший вариант, и есть гораздо более эффективные способы решения этой проблемы, созданные специально для этой проблемы.
Вероятно, наиболее эффективным способом является использование multiprocessing.Event
, например:
import multiprocessing
import sys
import os
def Code_One(event, fno):
proc_name = multiprocessing.current_process().name
print(f'running {proc_name}')
sys.stdin = os.fdopen(fno)
val = input('give proc 1 input: ')
print(f'proc 1 got input: {val}')
event.set()
def Code_Two(event, fno):
proc_name = multiprocessing.current_process().name
print(f'running {proc_name} and waiting...')
event.wait()
sys.stdin = os.fdopen(fno)
val = input('give proc 2 input: ')
print(f'proc 2 got input {val}')
if __name__ == '__main__':
event = multiprocessing.Event()
pression = multiprocessing.Process(name='code_one', target=Code_One, args=(event, sys.stdin.fileno()))
xgoals = multiprocessing.Process(name='code_two', target=Code_Two, args=(event, sys.stdin.fileno()))
xgoals.start()
pression.start()
xgoals.join()
pression.join()
Это создает объект event
и два подпроцесса. Объекты событий имеют внутренний флаг, который начинается с False
, а затем может быть переключен True
любым процессом, вызывающим event.set()
. Если процесс вызывает event.wait()
, когда установлен флаг False
, этот процесс будет заблокирован до тех пор, пока другой процесс не вызовет event.set()
.
event
создается в родительском процессе и передается каждому подпроцессу в качестве аргумента. Code_Two
начинает и вызывает event.wait()
, который блокируется до тех пор, пока внутренний флаг в event
не будет установлен на True
. Code_One
выполняется немедленно, а затем вызывает event.set()
, который устанавливает внутренний флаг event
в True
и позволяет Code_Two
продолжить работу. В этот момент оба процесса вернулись и вызвали join
, и программа завершается.
Это немного хакерски, потому что он также передает номер файла stdin
от родительского к дочернему процессу. Это необходимо, потому что при разветвлении подпроцессов эти файловые дескрипторы закрываются, поэтому, чтобы дочерний процесс мог читать stdin
с помощью input
, ему сначала нужно открыть правильный входной поток (именно это и делает sys.stdin = os.fdopen(fno)
). Не получится просто отправить sys.stdin
дочернему элементу в качестве еще одного аргумента из-за механики, которую Python использует для настройки среды для разветвленных процессов (sys.stdin
— это объект-оболочка ввода-вывода, который нельзя выбрать).
@BrondbyIF в том виде, в котором он был изначально написан (с использованием Condition
), фактически вводил состояние гонки, которое приводило к непредсказуемому поведению программы. Я обновил этот ответ, чтобы вместо этого использовать multiprocessing.event
, что избавляет от этой проблемы.
Привет @ Z4-tier, заранее спасибо за ваше время, я обновил вопрос, чтобы дать немного более реалистичный взгляд на дело, я привел пример очень простого использования только для того, чтобы доставить ошибку. В эти дни я пытался понять использование вашей индикации, но, честно говоря, мои попытки не увенчались успехом, он запрашивает ввод еще до запуска кодов.