2009-10-19 3 views
9

Voglio scrivere un programma che legge stdin (senza buffer) e scrive stdout (senza buffer) eseguendo alcune trasformazioni di tipo char-by-char. Per fare un esempio, diciamo che voglio rimuovere tutti i caratteri x dallo stdin.Come scrivere un filtro unix in python?

risposta

7

Non so esattamente che cosa si intende per tamponata in questo contesto, ma è abbastanza semplice da fare che cosa state chiedendo ...

so_gen.py (generando un flusso costante che possiamo guardare) :

import time 
import sys 
while True: 
    for char in 'abcdefx': 
     sys.stdout.write(char) 
     sys.stdout.flush() 
     time.sleep(0.1) 

so_filter.py (fare ciò che si chiede):

import sys 
while True: 
    char = sys.stdin.read(1) 
    if not char: 
     break 
    if char != 'x': 
     sys.stdout.write(char) 
     sys.stdout.flush() 

provare a eseguire python so_gen.py | python so_filter.py per vedere cosa fa.

+1

vincitore per la scrittura di 'if not char: break' – flybywire

+1

@flybywire: la sua risposta lo ha richiesto, nessun'altra risposta ha ... –

13

Leggere da sys.stdin e scrivere su sys.stdout (o utilizzare print). Il tuo programma di esempio:

import sys 

for line in sys.stdin: 
    print line.replace("x", ""), 

Non esiste un modo standard per fare stdin unbuffered, e non si vuole questo. Lascia che sia il buffer del sistema operativo.

+2

Ha detto "senza buffer" ma non sono sicuro che importi davvero. –

+0

Ho modificato la mia risposta come hai commentato. –

9

È possibile utilizzare lo fileinput class, che consente di elaborare gli input come farebbe l'operatore Diamante Perl. Dalla documentazione:

import fileinput 
for line in fileinput.input(): 
    process(line) 

processo in cui fa qualcosa di simile print line.replace('x','').

È possibile seguire this StackOverflow question per come annullare la stdout. Oppure puoi chiamare lo sys.stdout.flush() dopo ogni print.

+0

Ah! Questo rende tutto il lavoro extra che stavo facendo perché ho perso Perl per nulla! Ho bisogno di passare attraverso la libreria standard Python molto da vicino. –

2

Utilizzare l'opzione -u per l'interprete python per rendere tutte le letture e le scritture senza buffer. Simile all'impostazione di $| = true; in Perl. Quindi procedere come si farebbe, leggendo una riga modificandola e quindi stampandola. sys.stdout.flush() non richiesto.

#!/path/to/python -u 

import sys 

for line in sys.stdin: 
    process_line(line) 
+0

Non funziona qui ... –