2015-05-08 13 views
5

Cały kod napisany i przetestowany na Python 3.4 Windows 7.Python wieloprocesorowe stdin wejściowe

byłem projektując aplikację konsoli i miał potrzebę użycia stdin z linii poleceń (Win OS) do wydawania poleceń i aby zmienić tryb operacyjny programu. Program zależy od przetwarzania wieloprocesowego, aby poradzić sobie z obciążeniami cpu w celu rozprzestrzeniania się na wiele procesorów.

Używam stdout do monitorowania tego statusu i niektórych podstawowych informacji zwrotnych oraz standardowego wejścia do wydania komend ładujących różne podprocesy na podstawie zwróconych informacji konsolowych.

To tutaj znalazłem problem. Nie mogłem zmusić modułu wieloprocesorowego do zaakceptowania wejścia stdin, ale stdout działał dobrze. Myślę, że znalazłem następującą pomoc na stack Więc przetestowałem to i odkryłem, że z modułem threading to wszystko działa świetnie, z wyjątkiem faktu, że wszystkie wyjścia do stdout są wstrzymane do czasu, gdy stdin jest cyklowany z powodu blokady GIL z blokowaniem stdin.

Powiem, że odniosłem sukces dzięki pracy wdrożonej za pomocą msvcrt.kbhit(). Jednak nie mogę pomóc, ale zastanawiam się, czy jest jakiś błąd w funkcji wieloprocesowej, która sprawia, że ​​stdin nie odczytuje żadnych danych. Próbowałem na wiele sposobów i nic nie działało podczas korzystania z wieloprocesowości. Próbowałem nawet użyć Queues, ale nie próbowałem pule ani żadnych innych metod z przetwarzania wieloprocesowego.

Również nie próbowałem tego na moim komputerze z Linuksem, ponieważ koncentrowałem się na tym, żeby go uruchomić.

Tutaj jest uproszczony kod testowy, który nie funkcjonuje zgodnie z przeznaczeniem (przypomnienia ten został napisany w Pythonie 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() 

Mam nadzieję, że ktoś może rzucić światło na czy ten ma funkcjonalności, gdybym nie zrobił” t zaimplementuj go poprawnie lub inne użyteczne informacje.

Dzięki.

+0

W [wytyczne programowanie] (https://docs.python.org/3/ library/multiprocessing.html # programming-guidelines) omawiają, w jaki sposób 'sys.stdin' jest ustawione na' open (os.devnull) '. Dlatego czytasz z urządzenia Win32 'NUL' (np. NT' \ Device \ Null'). W 'function2' można przywrócić go jako' sys.stdin = open (0) '. – eryksun

+0

Rzeczywiście to działa. Miałem przeczucie, że może to być coś prostego, kiedy przeczytałem os.devnull, podejrzewałem, że być może będę musiał coś zrobić, aby zmienić ten stan. Zmieniłem powyższy program tak, aby obejmował sys.stdin = open (0) tuż przed pętlą while w funkcji 2 i odniósł sukces. Mam nadzieję, że inne osoby uznają te informacje za przydatne. Dziękuję za pomoc eryksun. – user2398421

Odpowiedz

4

Gdy przyjrzeć się realizacji pytony z multiprocessing.Process._bootstrap() widać to:

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

Można również potwierdzić za pomocą:

>>> 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'> 

I czytanie z os.devnull natychmiast zwraca pusty wynik:

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

Możesz pracować nad tym za pomocą open(0):

pliku albo jest ciągiem znaków lub bajtów obiektu umożliwiającego ścieżkę (absolutny lub względny do bieżącego katalogu roboczego) pliku, które zostaną otwarte lub pliku deskryptora całkowitej pliku będzie opakowane. (Jeśli deskryptor pliku jest podana, jest on zamknięty, gdy wrócił I/O obiekt jest zamknięty, chyba closefd jest ustawiona na False.)

I "0 file descriptor":

deskryptory plików są małe liczby całkowite odpowiadające do pliku, który został otwarty przez bieżący proces.Na przykład, standardowe wejście jest zwykle plik deskryptor 0, moc średnia wynosi 1, a odchylenie standardowe wynosi 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