Reading twice from STDIN

Discussion in 'Python' started by janedenone, Dec 1, 2011.

  1. janedenone

    janedenone Guest

    Hi,

    I would like to read from a pipe, parse the input and ask the user
    what to do next:

    message = sys.stdin.read()
    # message is parsed and URLs are printed as a list to choose from...
    selected_index = raw_input('Which URL to open?')

    Calling raw_input() always raises in an EOFError. I tried reopening
    and resetting sys.stdin, but nothing worked (at least on OX X 10.7,
    see http://stackoverflow.com/questions/8034595/python-raw-input-following-sys-stdin-read-throws-eoferror).

    I am surprised to find that a seemingly trivial task cannot be
    accomplished with Python 2.7 on a current Mac. Or am I missing
    something simple?

    - Jan
     
    janedenone, Dec 1, 2011
    #1
    1. Advertisements

  2. janedenone

    Gelonida N Guest

    On 12/01/2011 11:01 AM, janedenone wrote:
    Hi,

    With above line you said, that you want to read ALL data from stdin, so
    it's obvious that any following command will be unable to reda anything
    from standartd in Thus the EOF error.


    If you want to get input you had to read directly from the console (tty)
    and NOT from stdin. Stdin has already been consumed.

    It is possible in python to get the tty related to your console window
    and read from it.
    Unfortunately I don't kno whte commands by heart and I don't have time
    now to look it up.

    Perhaps somebody else can point you in the right direction.
    If not I'll it up till tomorrow.
     
    Gelonida N, Dec 1, 2011
    #2
    1. Advertisements

  3. You can read piped data from sys.stdin normally. Then if you want
    something from the user, at least on most *ix's, you would open
    /dev/tty and get user input from there. 'Not sure about OS/X.

    http://stackoverflow.com/questions/8034595/python-raw-input-following-sys-stdin-read-throws-eoferror).
     
    Dan Stromberg, Dec 2, 2011
    #3
  4. janedenone

    Hans Mulder Guest

    Reading from /dev/tty works fine on OS/X.

    -- HansM
     
    Hans Mulder, Dec 2, 2011
    #4
  5. janedenone

    janedenone Guest

    Many thanks for the pointers – I had tried

    sys.stdin = open('/dev/tty', 'r')

    but the actual solution is slightly more complicated. With your help
    (and another round of Google searches), I found exactly what I was
    looking for:

    http://turambar.org/jarkko/stdin_input.php

    Because raw_input() (input() in Python 3) reads from file descriptor
    0, the solution is to copy this file descriptor elsewhere, and use a
    file descriptor pointing to /dev/tty for the user input.

    Thanks again - Jan
     
    janedenone, Dec 2, 2011
    #5
  6. janedenone

    Hans Mulder Guest

    That seems to work for me. This code:

    import sys

    if sys.version_info.major == 2:
    input = raw_input

    for tp in enumerate(sys.stdin):
    print("%d: %s" % tp)

    sys.stdin = open('/dev/tty', 'r')
    answer = input('What is the carrying capacity of a swallow? ')
    print("You answered: %s" % answer)
    print("File descriptor is %d" % sys.stdin.fileno())

    .... does what I expect it to do in both Python 2.7 and Python 3.2.
    That's odd. For some reason, I can get away with a simple

    sys.stdin = open('/dev/tty')

    and raw_input will merrily read from file descriptor 3.

    I'm using Pyhton 2.7.1 and 3.2 on MacOS/X 10.5.0.

    What version are you using?

    -- HansM
     
    Hans Mulder, Dec 2, 2011
    #6
  7. janedenone

    janedenone Guest

    Python 2.7.1 and 3.2.2 on Mac OS X 10.7.2.

    But what's really strange – you're right. It works now. I have no idea
    what I did before, but I can confirm that the following code executes
    flawlessly:

    message = sys.stdin.read()
    urls = re.findall(r'(?:http|www)\S+', message)

    sys.stdin = open('/dev/tty')
    # Asks user to select a URL only if more than one URL is present
    if len(urls) > 1:
    for index, url in enumerate(urls):
    print '{0}: {1}\n'.format(index, url)

    selected_index = raw_input('Which URL to open? ')
    selected_index = int(selected_index)
    else:
    selected_index = 0
    selected_url = urls[selected_index]

    Quite embarrassing. In any case, I am happy to have found the simplest
    solution.

    Thanks again,
    Jan
     
    janedenone, Dec 2, 2011
    #7
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.