15

I want to write a program that reads stdin (unbuffered) and writes stdout (unbuffered) doing some trivial char-by-char transformation. For the sake of the example let's say I want to remove all chars x from stdin.

flybywire
  • 261,858
  • 191
  • 397
  • 503

4 Answers4

16

You can use the fileinput class, which lets you process inputs like the Perl diamond operator would. From the docs:

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

where process does something like print line.replace('x','').

You can follow this StackOverflow question for how to unbuffer stdout. Or you can just call sys.stdout.flush() after each print.

Community
  • 1
  • 1
Emil Sit
  • 22,894
  • 7
  • 53
  • 75
  • Ah! This makes all the extra work I was doing because I missed Perl for naught! I need to go through the Python standard library very closely. – Chris Lutz Oct 19 '09 at 17:42
  • This should be the accepted answer, the `fileinput` module is made exactly for this use case. – Antoine Gallix Jun 03 '19 at 15:47
15

Read from sys.stdin and write to sys.stdout (or use print). Your example program:

import sys

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

There isn't a standard way to make stdin unbuffered, and you don't want that. Let the OS buffer it.

Jed Smith
  • 15,584
  • 8
  • 52
  • 59
6

I don't know exactly what you mean by buffered in this context, but it is pretty simple to do what you are asking...

so_gen.py (generating a constant stream that we can watch):

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

so_filter.py (doing what you ask):

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

Try running python so_gen.py | python so_filter.py to see what it does.

Mike Boers
  • 6,665
  • 3
  • 31
  • 40
4

Use the -u switch for the python interpreter to make all reads and writes unbuffered. Similar to setting $| = true; in Perl. Then proceed as you would, reading a line modifying it and then printing it. sys.stdout.flush() not required.

#!/path/to/python -u

import sys

for line in sys.stdin:
    process_line(line)
EmFi
  • 23,435
  • 3
  • 57
  • 68