Recipe2.23.Reading an Unbuffered Character in a Cross-Platform Way


Recipe 2.23. Reading an Unbuffered Character in a Cross-Platform Way

Credit: Danny Yoo

Problem

Your application needs to read single characters, unbuffered, from standard input, and it needs to work on both Windows and Unix-like systems.

Solution

When we need a cross-platform solution, starting with platform-dependent ones, we need to wrap the different solutions so that they look the same:

try:     from msvcrt import getch except ImportError:     ''' we're not on Windows, so we try the Unix-like approach '''     def getch( ):         import sys, tty, termios         fd = sys.stdin.fileno( )         old_settings = termios.tcgetattr(fd)         try:             tty.setraw(fd)             ch = sys.stdin.read(1)         finally:             termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)         return ch

Discussion

On Windows, the standard Python library module msvcrt offers the handy getch function to read one character, unbuffered, from the keyboard, without echoing it to the screen. However, this module is not part of the standard Python library on Unix and Unix-like platforms, such as Linux and Mac OS X. On such platforms, we can get the same functionality with the tty and termios modules of the standard Python library (which, in turn, are not present on Windows).

The key point is that in application-level code, we should never have to worry about such issues; rather, we should write our application code in platform-independent ways, counting on library functions to paper over the differences between platforms. The Python Standard Library fulfills that role admirably for most tasks, but not all, and the problem posed by this recipe is an example of one for which the Python Standard Library doesn't directly supply a cross-platform solution.

When we can't find a ready-packaged cross-platform solution in the standard library, we should package it anyway as part of our own additional custom library. This recipe's Solution, besides solving the specific task of the recipe, also shows one good general way to go about such packaging. (Alternatively, you can test sys.platform, but I prefer the approach shown in this recipe.)

Your own library module should try to import the standard library module it needs on a certain platform within a TRy clause and include a corresponding except ImportError clause that is triggered when the module is running on a different platform. In the body of that except clause, your own library module can apply whatever alternate approach will work on the different platform. In some rare cases, you may need more than two platform-dependent approaches, but most often you'll need one approach on Windows and only one other approach to cover all other platforms. This is because most non-Windows platforms today are generally Unix or Unix-like.

See Also

Library Reference and Python in a Nutshell docs for msvcrt, tty, and termios.



Python Cookbook
Python Cookbook
ISBN: 0596007973
EAN: 2147483647
Year: 2004
Pages: 420

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net