Ascii Menu I/O redirection

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Hendrik van Rooyen

    Ascii Menu I/O redirection


    I am writing a small application with a simple ascii based menu.

    The menu is used to test individual functions, and to change some timings.
    Otherwise the application just runs automatically, depending on command
    line options.

    I want to be able to redirect the menu.
    The console, a serial port, or possibly a socket are target candidates.

    Now a serial port and a socket are single files, so I need a "file"
    that represents the console, to pass to the working functions.

    Simply re-assigning for instance sys.stdin.write to point to
    sys.stdout.writ e, and using sys.stdin as such a file does not work...

    So I do the following:

    <start code fragment>

    class console(object) :
    """
    This spoofs a single file like object, using stdout & - in
    (Minimalistic proof of concept implementation)
    """

    def __init__(self):
    self.read = sys.stdin.read
    self.readline = sys.stdin.readl ine
    self.write = sys.stdout.writ e
    self.flush = sys.stdout.flus h
    self.closeout = sys.stdout.clos e # keep references to close
    self.closein = sys.stdin.close

    def close(self):
    self.closein()
    self.closeout()

    # see if we must run, and how:

    if __name__ == "__main__":

    if 'serial' in sys.argv: # for RS-232 i/o to terminal
    f = open('/dev/ttyS0','r+b')
    else: # console i/o
    f = console()

    sys.stderr = f # redirect errors
    sys.stdout = f # redirect printing
    sys.stdin = f # redirect raw_input stuff

    if 'menu' in sys.argv: # test and timing changes
    menu_loop(menu_ dict,f) # (menu_dict is dispatch dict)
    else: # else just run the system
    autorun(menu_di ct,f)

    <end code fragment>

    The above just shows a choice between console and serial as an
    example - adding a socket option would be trivial.

    This all seems to work, but I am asking here before I take the
    trouble to turn it into production code, as I don't think it
    is exactly a new problem.

    Questions are:

    Is this a reasonable way of doing this kind of thing?
    Is there a canonical or better way of doing it?
    Am I missing something?

    Using Linux only.

    - Hendrik




  • Steven D'Aprano

    #2
    Re: Ascii Menu I/O redirection

    On Sat, 20 Sep 2008 23:14:26 +0200, Hendrik van Rooyen wrote:
    class console(object) :
    """
    This spoofs a single file like object, using stdout & - in
    (Minimalistic proof of concept implementation) """
    >
    def __init__(self):
    self.read = sys.stdin.read
    self.readline = sys.stdin.readl ine
    self.write = sys.stdout.writ e
    self.flush = sys.stdout.flus h
    self.closeout = sys.stdout.clos e # keep references to close
    self.closein = sys.stdin.close
    >
    def close(self):
    self.closein()
    self.closeout()

    I'm not sure that closing stdin and stout are a good idea. This could
    have side-effects for other parts of your program, and will almost
    certainly end badly if you're running in the interactive interpreter.

    Other than that, what you've done seems reasonable, although since every
    instance of console() has the same state, I'd write it slightly
    differently:

    class console(object) :
    """
    This spoofs a single file like object, using stdout & - in
    (Minimalistic proof of concept implementation)
    """
    read = sys.stdin.read
    readline = sys.stdin.readl ine
    write = sys.stdout.writ e
    flush = sys.stdout.flus h
    closeout = sys.stdout.clos e
    closein = sys.stdin.close
    @classmethod
    def close(cls):
    cls.closein()
    cls.closeout()



    [...]
    Questions are:
    >
    Is this a reasonable way of doing this kind of thing? Is there a
    canonical or better way of doing it? Am I missing something?
    It seems to me that you might have been better off to write your program
    to take two files, an input and an output, instead of forcing both to go
    to the same file.

    if 'serial' in sys.argv: # for RS-232 i/o to terminal
    infile = open('/dev/ttyS0','r+b')
    outfile = infile
    else: # console i/o
    infile = sys.stdin
    outfile = sys.stdout



    Hope this helps.


    --
    Steven

    Comment

    Working...