Problems with select() and stdin (solved)

jepler at unpythonic.net jepler at unpythonic.net
Wed Aug 21 00:03:52 CEST 2002


On Tue, Aug 20, 2002 at 07:10:36PM +0200, Iñigo Serna wrote:
> This runs ok with raw_input, but didn't work with my program, which uses
> (n)curses. I needed to include an explicit close.
> 
>         fd = select([sys.stdin], [], [], 1)[0][0]
>         stdin = ''.join(fd.readlines())
>         # close stdin (pipe) and open terminal for reading
>         os.close(0)
>         sys.stdin = open(os.ttyname(1), 'r')
> 
> And now everything works ok.

Ah -- I still wasn't thinking things through.  A program like ncurses is
going to depend on the fd number, not the value of sys.stdin.

If you don't want to read the full input upfront, you can use the following
code to get the original stdin on a different file, then open the tty as
standard input (untested):

    # Get a new Python file object which corresponds to the program's
    # original standard input but has a different fd (fileno)
    orig_stdin = os.fdopen(os.dup(0))

    # Create the terminal input 
    new_stdin = open("/dev/tty")

    # Force it to be fd (fileno) 0
    if new_stdin.fileno() != 0 :
	os.dup2(new_stdin.fileno(), 0)
	new_stdin.close()

    # Now open sys.stdin on the new terminal input
    sys.stdin = os.fdopen(0)

    # initialize ncurses or whatever
    ...

Since on every system I'm familiar with the open syscall returns
the lowest available fd, you'll always open fd0 after closing fd0, so your
code works due to this piece of luck.

If you want to have standard output as a pipe, but write something similar.
The fileno of stdout is 1, and you'd need to open for writing.

Jeff




More information about the Python-list mailing list