stdin: processing characters

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Kevin Simmons

    #1

    stdin: processing characters

    I have seen this question asked a few times but have not seen a
    clear answer...

    I have a python script that prompts the user for input from stdin via a
    menu. I want to process that input when the user types in two characters
    and not have to have the user press <CR>. As a comparison, in the bash
    shell one can use (read -n 2 -p "-->" CHOICE; case $CHOICE in...). Works
    great and is very
    straightforward . I have searched the python library and have not found
    an answer to this simply task. raw_input(n) won't do it. I have looked
    at the curses stuff but that is a bit overkill for what I need. I have
    tried a while statement reading in characters from sys.stdin but no luck
    there either. I am looking for an efficient way to do this simple task.

    Here is the bash code I want to do in python. I am only looking for help
    with the read of stdin portions, not the case statement:

    while [ "$1" == "" ]; do
    (echo " ---------")
    (echo " Functions")
    (echo " ---------")
    (echo " option")
    (echo " ------ ---- Scanning ----------")
    (echo " ss Scan the System, Run the scan tool.")
    (echo " rs Result of Scan, Show the result of the last
    scan.")

    read -e -n 2 -p "-->" CHOICE
    case "$CHOICE" in
    ## scanning
    "ss" | "SS" )
    (echo "Scanning the system may take a very long time. Do you
    wish to proceed?")
    read -e -n 1 -p "[y/n]-->" INPUT
    if [ "$INPUT" == "y" ]; then
    sh scan -s
    cd - &>/dev/null
    else
    (echo)
    (echo "Scan aborted.")
    fi
    ;;
    ... rest of case statement
    esac
    done
    --
    Kevin Simmons
    kps@sent.com

  • Edward Elliott

    #2
    Re: stdin: processing characters

    Kevin Simmons wrote:[color=blue]
    > I have a python script that prompts the user for input from stdin via a
    > menu. I want to process that input when the user types in two characters
    > and not have to have the user press <CR>. As a comparison, in the bash
    > shell one can use (read -n 2 -p "-->" CHOICE; case $CHOICE in...). Works
    > great and is very[/color]

    I did something like this a couple years ago, curses was the easiest way I
    found to do it. It's pretty painless with the wrapper function, which
    restores your terminal on error/exit.

    Comment

    • Cameron Laird

      #3
      Re: stdin: processing characters

      In article <2Bd4g.21380$tN 3.16246@newssvr 27.news.prodigy .net>,
      Edward Elliott <nobody@127.0.0 .1> wrote:[color=blue]
      >Kevin Simmons wrote:[color=green]
      >> I have a python script that prompts the user for input from stdin via a
      >> menu. I want to process that input when the user types in two characters
      >> and not have to have the user press <CR>. As a comparison, in the bash
      >> shell one can use (read -n 2 -p "-->" CHOICE; case $CHOICE in...). Works
      >> great and is very[/color]
      >
      >I did something like this a couple years ago, curses was the easiest way I
      >found to do it. It's pretty painless with the wrapper function, which
      >restores your terminal on error/exit.
      >[/color]

      Kevin, the bad news is that curses() is as good as Python gets in
      this regard. For better or worse, to the best of my knowledge,
      unextended Python caNOT implement bash's read. Here's the closest
      small approximation I know:

      import curses
      import os

      msvcrt = curses.initscr( )
      msvcrt.addstr("-->")
      first = msvcrt.getch()
      second = msvcrt.getch()
      os.system("stty echo -nl")
      print "\nThe two characters are '%s' and '%s'." % (first, second)

      I hope someone proves me wrong.

      Comment

      • Serge Orlov

        #4
        Re: stdin: processing characters


        Cameron Laird wrote:[color=blue]
        > In article <2Bd4g.21380$tN 3.16246@newssvr 27.news.prodigy .net>,
        > Edward Elliott <nobody@127.0.0 .1> wrote:[color=green]
        > >Kevin Simmons wrote:[color=darkred]
        > >> I have a python script that prompts the user for input from stdin via a
        > >> menu. I want to process that input when the user types in two characters
        > >> and not have to have the user press <CR>. As a comparison, in the bash
        > >> shell one can use (read -n 2 -p "-->" CHOICE; case $CHOICE in...). Works
        > >> great and is very[/color]
        > >
        > >I did something like this a couple years ago, curses was the easiest way I
        > >found to do it. It's pretty painless with the wrapper function, which
        > >restores your terminal on error/exit.
        > >[/color]
        >
        > Kevin, the bad news is that curses() is as good as Python gets in
        > this regard. For better or worse, to the best of my knowledge,
        > unextended Python caNOT implement bash's read. Here's the closest
        > small approximation I know:
        >
        > import curses
        > import os
        >
        > msvcrt = curses.initscr( )
        > msvcrt.addstr("-->")
        > first = msvcrt.getch()
        > second = msvcrt.getch()
        > os.system("stty echo -nl")
        > print "\nThe two characters are '%s' and '%s'." % (first, second)
        >
        > I hope someone proves me wrong.[/color]

        I'm not sure what "unextended Python" means, but on POSIX platforms
        termios module can disable echo and command line option -u can disable
        buffering. I think there should be a way to disable buffering after
        program started. Probably fcntl module.

        Comment

        • Kevin Simmons

          #5
          Re: stdin: processing characters

          Serge Orlov wrote:[color=blue]
          > Cameron Laird wrote:[color=green]
          >> In article <2Bd4g.21380$tN 3.16246@newssvr 27.news.prodigy .net>,
          >> Edward Elliott <nobody@127.0.0 .1> wrote:[color=darkred]
          >>> Kevin Simmons wrote:
          >>>> I have a python script that prompts the user for input from stdin via a
          >>>> menu. I want to process that input when the user types in two characters
          >>>> and not have to have the user press <CR>. As a comparison, in the bash
          >>>> shell one can use (read -n 2 -p "-->" CHOICE; case $CHOICE in...). Works
          >>>> great and is very
          >>> I did something like this a couple years ago, curses was the easiest way I
          >>> found to do it. It's pretty painless with the wrapper function, which
          >>> restores your terminal on error/exit.
          >>>[/color]
          >> Kevin, the bad news is that curses() is as good as Python gets in
          >> this regard. For better or worse, to the best of my knowledge,
          >> unextended Python caNOT implement bash's read. Here's the closest
          >> small approximation I know:
          >>
          >> import curses
          >> import os
          >>
          >> msvcrt = curses.initscr( )
          >> msvcrt.addstr("-->")
          >> first = msvcrt.getch()
          >> second = msvcrt.getch()
          >> os.system("stty echo -nl")
          >> print "\nThe two characters are '%s' and '%s'." % (first, second)
          >>
          >> I hope someone proves me wrong.[/color]
          >
          > I'm not sure what "unextended Python" means, but on POSIX platforms
          > termios module can disable echo and command line option -u can disable
          > buffering. I think there should be a way to disable buffering after
          > program started. Probably fcntl module.
          >[/color]
          Thanks for your input. I found an answer that suits my needs, not curses
          :-), but stty settings and sys.stdin.read( n) :

          import os, sys

          while 1:
          os.system("stty -icanon min 1 time 0")
          print """
          Radio computer control program.
          ------------------------------
          Choose a function:
          po) Power toggle
          fq) Change frequency
          cm) Change mode
          vo) Change volume
          re) Reset
          qu) Quit
          -->""",
          func = sys.stdin.read( 2)
          if func == "po":
          ...
          ... rest of menu actions ...
          elif func = "qu":
          os.system("stty cooked")
          sys.exit()

          Thanks again,
          Kevin

          Comment

          • Serge Orlov

            #6
            Re: stdin: processing characters

            Kevin Simmons wrote:[color=blue]
            > Thanks for your input. I found an answer that suits my needs, not curses
            > :-), but stty settings and sys.stdin.read( n) :
            >
            > import os, sys
            >
            > while 1:
            > os.system("stty -icanon min 1 time 0")
            > print """
            > Radio computer control program.
            > ------------------------------
            > Choose a function:
            > po) Power toggle
            > fq) Change frequency
            > cm) Change mode
            > vo) Change volume
            > re) Reset
            > qu) Quit
            > -->""",
            > func = sys.stdin.read( 2)
            > if func == "po":
            > ...
            > ... rest of menu actions ...
            > elif func = "qu":
            > os.system("stty cooked")
            > sys.exit()
            >[/color]

            Looks reasonable if you don't need portability. But you may want to
            refactor it a little bit to make sure terminal setting are always
            restored:

            try:
            do_all_the_work ()
            finally:
            os.system("stty cooked")

            P.S. Maybe its me, but when I see call sys.exit() I always have a gut
            feeling this function never returns. But in fact my I'm wrong and
            sys.exit is more reasonable: it raises exception. So you can call
            sys.exit() inside do_all_the_work and you can still be sure that
            os.system("stty cooked") is always executed at the end.

            Comment

            • Russ Salsbury

              #7
              Re: stdin: processing characters

              Serge Orlov wrote:[color=blue]
              > Kevin Simmons wrote:[/color]

              [color=blue]
              >
              > Looks reasonable if you don't need portability. But you may want to
              > refactor it a little bit to make sure terminal setting are always
              > restored:
              >
              > try:
              > do_all_the_work ()
              > finally:
              > os.system("stty cooked")
              >[/color]

              IIRC You need to do "stty raw" first. The last time I had to do this
              was in the '80's, so take for what it's worth.

              Russ

              Comment

              Working...