2015-05-08 10 views
5

Tutto il codice scritto e testato su Python 3.4 Windows 7.Python multiprocessing stdin ingresso

stavo progettando una console app e aveva la necessità di utilizzare stdin da riga di comando (Win OS) per impartire comandi e per cambiare il modalità operativa del programma. Il programma dipende dal multiprocessing per gestire i carichi associati alla CPU da diffondere a più processori.

Sto utilizzando stdout per monitorare lo stato e alcune informazioni di ritorno di base e stdin per emettere comandi per caricare diversi sottoprocessi in base alle informazioni della console restituite.

Questo è dove ho trovato un problema. Non ho potuto ottenere il modulo multiprocessing per accettare gli input stdin ma stdout funzionava perfettamente. Penso che abbia trovato il seguente aiuto su stack Quindi l'ho provato e ho trovato che con il modulo di thread tutto funziona alla grande, eccetto il fatto che tutto l'output su stdout è sospeso fino a quando ogni stdin è ciclato a causa del blocco GIL con stdin blocking.

Dirò che ho avuto successo con un lavoro su implementato con msvcrt.kbhit(). Tuttavia, non posso fare a meno di chiedermi se c'è una sorta di bug nella funzione di multiprocessing che sta facendo stdin non leggere alcun dato. Ho provato numerosi modi e nulla ha funzionato quando si utilizza il multiprocessing. Ho persino tentato di usare le code, ma non ho provato i pool o altri metodi di multiprocessing.

Inoltre non ho provato questo sul mio computer Linux da quando mi sono concentrato sul tentativo di farlo funzionare.

Qui è semplificato codice di prova che non funziona come previsto (ricordo questo è stato scritto in 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() 

Speriamo che qualcuno può far luce sulla funzionalità se questo è destinato, se io didn' implementarlo correttamente o qualche altro utile bit di informazione.

Grazie.

+0

Le linee guida di programmazione [] (https://docs.python.org/3/ library/multiprocessing.html # programming-guidelines) spiega come 'sys.stdin' è impostato su' open (os.devnull) '. Quindi stai leggendo dal dispositivo 'NUL' di Win32 (ad esempio NT' \ Device \ Null'). In 'function2' puoi ripristinarlo come' sys.stdin = open (0) '. – eryksun

+0

Effettivamente questo funziona. Ho avuto la sensazione che potrebbe essere qualcosa di semplice come questo quando ho letto l'os.devnull che avevo sospettato che potrei aver bisogno di fare qualcosa per cambiare quello stato. Ho modificato il programma precedente per includere sys.stdin = open (0) subito prima del ciclo while nella funzione 2 e ottenuto il successo. Speriamo che gli altri trovino questa informazione utile. Grazie per l'assistenza eryksun. – user2398421

risposta

4

Quando si dà un'occhiata alla implementazione Pythons della multiprocessing.Process._bootstrap() si vedrà questo:

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

Si può anche verificare questo utilizzando:

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

e la lettura da os.devnull restituisce immediatamente risultato vuoto:

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

È possibile lavorare questo intorno utilizzando open(0):

lima è una stringa o byte oggetto dà il percorso (assoluto o relativo alla directory di lavoro corrente) del file da aprire o un file descrittore intero del file da avvolto. (Se viene dato un descrittore di file, è chiuso quando la tornata di I/O oggetto è chiuso, a meno che non closefd è impostato su False.)

E "0 file descriptor":

descrittori di file sono piccoli numeri interi corrispondenti a un file che è stato aperto dal processo corrente.Ad esempio, standard input è di solito descrittore di file 0, uscita standard è 1, e l'errore standard è 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