tags:

views:

46

answers:

3

Can I write a python program that read from a piped stdin and keyboard?

What I mean? I want to be able to use it in this way:

tail -f LOGFILE | myscript.py

see the log lines appearing in the screen and type commands with the keyboard?

This sounds like 2 stdin and that confuse me. Is it possible or is it conceptually wrong?

Thanks!

+2  A: 

Possible solution would be to grab the users current tty and attach a file stream to the corresponding /dev/tty entry.

This may allow you to grab the keyboard input while using stdin as your piped log file.

davydotcom
Could you give me an example in code (preferentially Python) to understand what you say?
Juanjo Conti
`kbdin = open('/dev/tty', 'r')`
Ignacio Vazquez-Abrams
+1  A: 

This might be hackable, but it is conceptually wrong seems weird to me. stdin is a single input stream. Issuing the command

... | program.py

changes stdin to be the stdout of whatever came before the pipe. But accepting keyboard input means reading the original stdin -- you can't have your cake and eat it too!

A hack would merge those two streams into one, but that's not a good way of doing it; it doesn't separate the data correctly. If your program really should accept keyboard input as well as piped data (are you sure that it should? that seems like an awfully counterintuitive thing to want!), the right way to do it is to spawn separate threads to handle each of the input streams.

katrielalex
What HOW do you split them in first place?
Juanjo Conti
@Juanjo: huh? The streams are already 'split' -- they are two different inputs!
katrielalex
I dont see it in code.
Juanjo Conti
If this idea were really conceptually wrong, we should remove `more` and `less` and most terminal-based editors from our systems, right?
JanC
@Jan: you're right, I was too strong. I guess I don't like the idea of `cat foo.txt | less` and having it take keyboard input.
katrielalex
+2  A: 

Make your script take a file argument, then use bash's ability to create an anonymous fifo:

myscript.py <( tail -f LOGFILE )

bash translates this to (roughly):

mkfifo /tmp/UNIQUEFILENAME
tail -f LOGFILE > /tmp/UNIQUEFILENAME &
myscript.py /tmp/UNIQUEFILENAME

Have only the commands come through stdin.

<() and >(), especially when combined with tee, can be used anytime you want to create a "branch" in an either side of an arbitrary bash pipeline.

charles