Если два многопроцессорных процесса могут запрашивать ввод на терминале, есть ли способ приостановить один из них, пока не будет дан ответ?

Как видно из приведенного ниже кода, две многопроцессорные обработки выполняются вместе, но у обеих есть момент, который может запросить 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
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
3
0
65
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Конечно, это возможно. Для этого вам нужно будет использовать какой-то механизм межпроцессного взаимодействия (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 — это объект-оболочка ввода-вывода, который нельзя выбрать).

Привет @ Z4-tier, заранее спасибо за ваше время, я обновил вопрос, чтобы дать немного более реалистичный взгляд на дело, я привел пример очень простого использования только для того, чтобы доставить ошибку. В эти дни я пытался понять использование вашей индикации, но, честно говоря, мои попытки не увенчались успехом, он запрашивает ввод еще до запуска кодов.

Brondby IF 25.03.2022 21:30

@BrondbyIF в том виде, в котором он был изначально написан (с использованием Condition), фактически вводил состояние гонки, которое приводило к непредсказуемому поведению программы. Я обновил этот ответ, чтобы вместо этого использовать multiprocessing.event, что избавляет от этой проблемы.

Z4-tier 29.03.2022 05:52

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