2015-05-08 3 views
5

Весь код написан и протестирован на питона 3.4 окна 7.Python многопроцессорной обработки стандартного устройства ввода входных

я проектировал консольного приложения и имел необходимость использовать STDIN из командной строки (Win OS) для выдачи команд и изменения режим работы программы. Программа зависит от многопроцессорности, связанной с нагрузками, связанными с процессором, для распространения на несколько процессоров.

Я использую stdout для контроля этого состояния и некоторой базовой информации о возврате и stdin для выдачи команд для загрузки разных подпроцессов на основе возвращаемой информации о консоли.

Здесь я нашел проблему. Я не мог заставить мультипроцессорный модуль принимать входные данные stdin, но stdout работал нормально. Я думаю, нашел следующую помощь на stack Итак, я протестировал ее и обнаружил, что с модулем потоковой передачи все это отлично работает, за исключением того, что весь вывод на stdout приостанавливается до тех пор, пока каждый цикл stdin не будет циклическим из-за блокировки GIL с блокировкой stdin.

Я скажу, что у меня была успешная работа, реализованная с помощью msvcrt.kbhit(). Однако я не могу не задаться вопросом, есть ли какая-то ошибка в многопроцессорной функции, которая заставляет stdin не читать какие-либо данные. Я пробовал множество способов, и при использовании многопроцессорной обработки ничего не работало. Даже пытались использовать Очереди, но я не пробовал пулы или другие методы многопроцессорности.

Я также не пробовал это на своей машине с Linux, так как был сосредоточен на попытке заставить его работать.

Здесь упрощен тестовый код, который не функционирует по назначению (напоминания это было написано в Python 3.4 - win7):

import sys 
import time 
from multiprocessing import Process 

def function1(): 
    while True: 
     print("Function 1") 
     time.sleep(1.33) 

def function2(): 
    while True: 
     print("Function 2") 
     c = sys.stdin.read(1) # Does not appear to be waiting for read before continuing loop. 
     sys.stdout.write(c) #nothing in 'c' 
     sys.stdout.write(".") #checking to see if it works at all. 
     print(str(c)) #trying something else, still nothing in 'c' 
     time.sleep(1.66) 

if __name__ == "__main__": 
    p1 = Process(target=function1) 
    p2 = Process(target=function2) 
    p1.start() 
    p2.start() 

Надеется кто-то может пролить свет на ли это предполагаемая функциональности, если я Жду» t реализовать его правильно или какой-либо другой полезный бит информации.

Спасибо.

+0

В [Руководство по программированию] (https://docs.python.org/3/ library/multiprocessing.html # programming-guidelines) обсуждают, как 'sys.stdin' установлен в' open (os.devnull) '. Таким образом, вы читаете с устройства Win32 'NUL' (т. Е. NT' \ Device \ Null'). В 'function2' вы можете восстановить его как' sys.stdin = open (0) '. – eryksun

+0

Действительно, это действительно работает. У меня было ощущение, что это может быть что-то простое, когда я читаю os.devnull, я подозревал, что мне, возможно, нужно что-то сделать, чтобы изменить это состояние. Я изменил вышеуказанную программу, чтобы включить sys.stdin = open (0) прямо перед циклом while в функции 2 и получил успех. Будем надеяться, что эта информация будет полезной. Благодарим вас за помощь eryksun. – user2398421

ответ

4

Когда вы посмотрите на реализацию питоны из multiprocessing.Process._bootstrap() вы увидите следующее:

if sys.stdin is not None: 
    try: 
     sys.stdin.close() 
     sys.stdin = open(os.devnull) 
    except (OSError, ValueError): 
     pass 

Вы также можете подтвердить это с помощью:

>>> import sys 
>>> import multiprocessing 
>>> def func(): 
...  print(sys.stdin) 
... 
>>> p = multiprocessing.Process(target=func) 
>>> p.start() 
>>> <_io.TextIOWrapper name='/dev/null' mode='r' encoding='UTF-8'> 

И чтение из os.devnull немедленно возвращает пустой результат:

>>> import os 
>>> f = open(os.devnull) 
>>> f.read(1) 
'' 

Вы можете это сделать с помощью open(0):

файл является строкой или байтов объект давая путь (абсолютный или относительно текущего рабочего каталога) файла, который будет открыт или дескриптора файла целого файла будет завернутый. (Если дескриптор файла задан, он будет закрыт, когда возвращаемый I/объект O будет закрыт, если closefd не установлен в значение False.)

И "0 file descriptor":

Файловые дескрипторы представляют собой небольшие целые числа, соответствующие к файлу, который был открыт текущим процессом.Например, стандартного ввода, как правило, файл дескриптора 0, стандартный вывод 1, и стандартная ошибка 2:

>>> def func(): 
...  sys.stdin = open(0) 
...  print(sys.stdin) 
...  c = sys.stdin.read(1) 
...  print('Got', c) 
... 
>>> multiprocessing.Process(target=func).start() 
>>> <_io.TextIOWrapper name=0 mode='r' encoding='UTF-8'> 
Got a 
Смежные вопросы