Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: How can I use GNU readline when the value of sys.stdin has been changed?

I want my Python program to take input from a pipe and later take input from the terminal. After reading this SO post, I tried opening /dev/tty to replace sys.stdin.

import sys
import readline

def tty_input(prompt):
    with open("/dev/tty") as terminal:
        sys.stdin = terminal
        user_input = input(prompt)
    sys.stdin = sys.__stdin__
    return user_input

The problem with this approach is that GNU readline doesn't work when sys.stdin != sys.__stdin__. I can't use the arrow keys to move the cursor or navigate the history. I read of a patch for this very issue that was submitted here, but I'm guessing that nothing came of it.

If there is a way to accept input from both a pipe and the terminal without changing the value of sys.stdin, I'm open to suggestions.

like image 661
Wren Avatar asked Nov 08 '22 04:11

Wren


1 Answers

I bet that sys.stdin and sys.__stdin__ are not what you think they are. I would save off the original sys.stdin before reassigning it.

import sys
import readline

def tty_input(prompt):
    oldStdin = sys.stdin
    with open("/dev/tty") as terminal:
        sys.stdin = terminal
        user_input = input(prompt)
    sys.stdin = oldStdin
    return user_input

Or make a copy

import sys
import readline
import copy

def tty_input(prompt):
    oldStdin = copy.copy(sys.stdin)
    with open("/dev/tty") as terminal:
        sys.stdin = terminal
        user_input = input(prompt)
    sys.stdin = oldStdin
    return user_input
like image 166
shrewmouse Avatar answered Nov 14 '22 23:11

shrewmouse