Python/FAQ/Пользовательский интерфейс

Материал из Wiki.crossplatform.ru

Перейти к: навигация, поиск
· Python ·

Содержание

Parsing Program Arguments

#-----------------------------
# Parsing program arguments
# -- getopt way (All Python versions)
 
#-----------------------------
 
# Preamble
 
import sys
import getopt
 
# getopt() explicitly receives arguments for it to process.
# No magic. Explicit is better than implicit.
 
# PERL: @ARGV
argv = sys.argv[1:]
 
 
# Note that sys.argv[0] is the script name, and need to be
# stripped.
 
#-----------------------------
# Short options
 
# PERL: getopt("vDo");
# Polluting the caller's namespace is evil. Don't do that.
 
# PERL: getopt("vDo:", \%opts);
 
opts, rest = getopt.getopt(argv, "vDo:")
 
# If you want switches to take arguments, you must say so.
# Unlike PERL, which silently performs its magic, switches
# specified without trailing colons are considered boolean
# flags by default.
 
# PERL: getopt("vDo", \%opts);
opts, rest = getopt.getopt(argv, "v:D:o:")
 
 
# PERL: getopts("vDo:", \%opts);
# getopt/getopts distinction is not present in Python 'getopt'
# module.
 
#-----------------------------
# getopt() return values, compared to PERL
 
# getopt() returns two values. The first is a list of
# (option, value) pair. (Not a dictionary, i.e. Python hash.)
# The second is the list of arguments left unprocessed.
 
 
# Example
# >>> argv = "-v ARG1 -D ARG2 -o ARG3".split()
# >>> opts, rest = getopt.getopt(argv, "v:D:o:")
# >>> print opts
# [('-v', 'ARG1'), ('-D', 'ARG2'), ('-o', 'ARG3')]
 
#-----------------------------
 
# Long options
 
# getopt() handles long options too. Pass a list of option
# names as the third argument. If an option takes an argument,
# append an equal sign.
 
opts, rest = getopt.getopt(argv, "", [
    "verbose", "Debug", "output="])
 
 
#-----------------------------
# Switch clustering
 
# getopt() does switch clustering just fine.
 
# Example
# >>> argv1 = '-r -f /tmp/testdir'.split()
# >>> argv2 = '-rf /tmp/testdir'.split()
# >>> print getopt.getopt(argv1, 'rf')
 
# ([('-r', ''), ('-f', '')], ['/tmp/testdir'])
# >>> print getopt.getopt(argv2, 'rf')
# ([('-r', ''), ('-f', '')], ['/tmp/testdir'])
 
#-----------------------------
# @@INCOMPLETE@@
 
# TODO: Complete this section using 'getopt'. Show how to
# use the parsed result.
 
 
# http://www.python.org/doc/current/lib/module-getopt.html
# Python library reference has a "typical usage" demo.
 
# TODO: Introduce 'optparse', a very powerful command line
# option parsing module. New in 2.3.

Testing Whether a Program Is Running Interactively

##------------------
import sys
 
def is_interactive_python():
    try:
 
        ps = sys.ps1
    except:
        return False
    return True
##------------------
import sys
 
def is_interactive():
    # only False if stdin is redirected like "-t" in perl.
    return sys.stdin.isatty()
 
# Or take advantage of Python's Higher Order Functions:
is_interactive = sys.stdin.isatty
##------------------
import posix
 
def is_interactive_posix():
    tty = open("/dev/tty")
    tpgrp = posix.tcgetpgrp(tty.fileno())
    pgrp = posix.getpgrp()
    tty.close()
    return (tpgrp == pgrp)
 
# test with:
#  python 15.2.py
#  echo "dummy" | python 15.2.py | cat
 
print "is python shell:", is_interactive_python()
print "is a tty:", is_interactive()
print "has no tty:", is_interactive_posix()
 
if is_interactive():
    while True:
        try:
 
            ln = raw_input("Prompt:")
        except:
            break
        print "you typed:", ln

Clearing the Screen

# Python has no Term::Cap module.
# One could use the curses, but this was not ported to windows,
# use console.
 
# just run clear
import os
os.system("clear")
# cache output
clear = os.popen("clear").read()
 
print clear
# or to avoid print's newline
sys.stdout.write(clear)

Determining Terminal or Window Size

# Determining Terminal or Window Size
 
# eiter use ioctl
import struct, fcntl, termios, sys
 
s = struct.pack("HHHH", 0, 0, 0, 0)
hchar, wchar = struct.unpack("HHHH", fcntl.ioctl(sys.stdout.fileno(),
                                 termios.TIOCGWINSZ, s))[:2]
 
# or curses
import curses
(hchar,wchar) = curses.getmaxyx()
 
# graph contents of values
import struct, fcntl, termios, sys
width = struct.unpack("HHHH", fcntl.ioctl(sys.stdout.fileno(),
                                 termios.TIOCGWINSZ, 
                                 struct.pack("HHHH", 0, 0, 0, 0)))[1]
if width<10:
    print "You must have at least 10 characters"
 
    raise SystemExit
 
max_value = 0                    
for v in values:
    max_value = max(max_value,v)
 
ratio = (width-10)/max_value   # chars per unit
 
for v in values:
    print "%8.1f %s" % (v, "*"*(v*ratio))

Changing Text Color

# there seems to be no standard ansi module
 
# and BLINK does not blink here.
RED = '\033[31m'
RESET = '\033[0;0m'
BLINK = '\033[05m'
NOBLINK = '\033[25m'
 
print RED+"DANGER, Will Robinson!"+RESET
 
print "This is just normal text"
print "Will ``"+BLINK+"Do you hurt yet?"+NOBLINK+"'' and back"

Reading from the Keyboard

# Show ASCII values for keypresses
 
# _Getch is from http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/134892
 
class _Getch:
    """Gets a single character from standard input.  Doesn't echo to screen."""
    def __init__(self):
        try:
            self.impl = _GetchWindows()
        except ImportError:
            self.impl = _GetchUnix()
 
    def __call__(self):
        return self.impl()
 
 
 
class _GetchUnix:
    def __init__(self):
        import tty, sys
 
    def __call__(self):
        import sys, tty, termios
        fd = sys.stdin.fileno()
        old_settings = termios.tcgetattr(fd)
        try:
 
            tty.setraw(sys.stdin.fileno())
            ch = sys.stdin.read(1)
        finally:
            termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
        return ch
 
 
class _GetchWindows:
    def __init__(self):
        import msvcrt
 
    def __call__(self):
        import msvcrt
        return msvcrt.getch()
 
 
getch = _Getch()
 
 
print "Press keys to see their ASCII values.  Use Ctrl-C to quit.\n"
try:
    while True:
        char = ord(getch())
        if char == 3:
            break
 
        print " Decimal: %3d   Octal: %3o   Hex: x%02x" % (char, char, char)
except KeyboardError:
    pass
#----------------------------------------

Ringing the Terminal Bell

print "\aWake up!\n";
 
#----------------------------------------
# @@INCOMPLETE@@

Using POSIX termios

# @@INCOMPLETE@@
# @@INCOMPLETE@@

Checking for Waiting Input

# On Windows
import msvcrt
if msvcrt.kbhit():
    c = msvcrt.getch
 
 
# See http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/134892
# @@INCOMPLETE@@

Reading Passwords

#----------------------------------------
import getpass
import pwd
import crypt
password = getpass.getpass('Enter your password: ')
username = getpass.getuser()
encrypted = pwd.getpwnam(username).pw_passwd
 
if not encrypted or encrypted == 'x':
    # If using shadow passwords, this will be empty or 'x'
    print "Cannot verify password"
 
elif crypt.crypt(password, encrypted) != encrypted:
    print "You are not", username
else:
    print "Welcome,", username
#----------------------------------------

Editing Input

# simply importing readline gives line edit capabilities to raw_
import readline
readline.add_history("fake line")
line = raw_input()
 
# download the following standalone program
#!/usr/bin/python
# vbsh - very bad shell
 
 
import os
import readline
 
while True:
    try:
        cmd = raw_input('$ ')
    except EOFError:
        break
 
    status = os.system(cmd)
    exit_value = status >> 8
    signal_num = status & 127
    dumped_core = status & 128 and "(core dumped)" or ""
    print "Program terminated with status %d from signal %d%s\n" % (
            exit_value, signal_num, dumped_core)
 
 
 
readline.add_history("some line!")
readline.remove_history_item(position)
line = readline.get_history_item(index)
 
 
# an interactive python shell would be
import code, readline
code.InteractiveConsole().interact("code.InteractiveConsole")

Managing the Screen

# @@INCOMPLETE@@
# @@INCOMPLETE@@

Controlling Another Program with Expect

#----------------------------------------
# This entry uses pexpect, a pure Python Expect-like module.
 
# http://pexpect.sourceforge.net/
 
# for more information, check pexpect's documentation and example.
 
import pexpect
 
#----------------------------------------
# spawn program
try:
    command = pexpect.spawn("program to run")
 
except pexpect.ExceptionPexpect:
    # couldn't spawn program
    pass
 
#----------------------------------------
# you can pass any filelike object to setlog
# passing None will stop logging
 
# stop logging
 
command.setlog(None)
 
# log to stdout
import sys
command.setlog(sys.stdout)
 
# log to specific file
fp = file("pexpect.log", "w")
command.setlog(fp)
 
 
#----------------------------------------
# expecting simple string
command.expect("ftp>")
 
# expecting regular expression
# actually, string is always treated as regular expression
 
# so it's the same thing
command.expect("Name.*:")
 
 
# you can do it this way, too
import re
regex = re.compile("Name.*:")
command.expect(regex)
 
#----------------------------------------
# expecting with timeout
try:
    command.expect("Password:", 10)
 
except pexpect.TIMEOUT:
    # timed out
    pass
 
# setting default timeout
command.timeout = 10
 
# since we set default timeout, following does same as above
try:
    command.expect("Password:")
 
except pexpect.TIMEOUT:
    # timed out
    pass
 
#----------------------------------------
# what? do you *really* want to wait forever?
 
#----------------------------------------
# sending line: normal way
 
command.sendline("get spam_and_ham")
 
# you can also treat it as file
print>>command, "get spam_and_ham"
 
#----------------------------------------
# finalization
 
# close connection with child process
 
# (that is, freeing file descriptor)
command.close()
 
# kill child process
import signal
command.kill(signal.SIGKILL)
 
#----------------------------------------
# expecting multiple choices
which = command.expect(["invalid", "success", "error", "boom"])
 
 
# return value is index of matched choice
# 0: invalid
# 1: success
# 2: error
# 3: boom
 
#----------------------------------------
# avoiding exception handling
choices = ["invalid", "success", "error", "boom"]
choices.append(pexpect.TIMEOUT)
choices.append(pexpect.EOF)
 
which = command.expect(choices)
 
 
# if TIMEOUT or EOF occurs, appropriate index is returned
# (instead of raising exception)
# 4: TIMEOUT
# 5: EOF

Creating Menus with Tk

from Tkinter import *
 
def print_callback():
    print "print_callback"
 
main = Tk()
 
menubar = Menu(main)
main.config(menu=menubar)
 
file_menu = Menu(menubar)
menubar.add_cascade(label="File", underline=1, menu=file_menu)
file_menu.add_command(label="Print", command=print_callback)
 
main.mainloop()
 
# using a class
from Tkinter import *
 
class Application(Tk):
    def print_callback(self):
        print "print_callback"
 
    def debug_callback(self):
        print "debug:", self.debug.get()
        print "debug level:", self.debug_level.get()
 
    def createWidgets(self):
        menubar = Menu(self)
        self.config(menu=menubar)
        file_menu = Menu(menubar)
        menubar.add_cascade(label="File",      
                    underline=1, menu=file_menu)
        file_menu.add_command(label="Print",
                command=self.print_callback)
        file_menu.add_command(label="Quit Immediately",
                command=sys.exit)
        # 
 
        options_menu = Menu(menubar)
        menubar.add_cascade(label="Options",
                underline=0, menu=options_menu)
        options_menu.add_checkbutton(
                label="Create Debugging File",
                variable=self.debug,
                command=self.debug_callback,
                onvalue=1, offvalue=0)
        options_menu.add_separator()
        options_menu.add_radiobutton(
                label = "Level 1",
                variable = self.debug_level,
                value = 1
                )
        options_menu.add_radiobutton(
                label = "Level 2",
                variable = self.debug_level,
                value = 2
                )
        options_menu.add_radiobutton(
                label = "Level 3",
                variable = self.debug_level,
                value = 3
                )
 
    def __init__(self, master=None):
        Tk.__init__(self, master)
        # bound variables must be IntVar, StrVar, ...
 
        self.debug = IntVar()
        self.debug.set(0)
        self.debug_level = IntVar()
        self.debug_level.set(1)
        self.createWidgets()
 
app = Application()
app.mainloop()

Creating Dialog Boxes with Tk

# @@INCOMPLETE@@
# @@INCOMPLETE@@

Responding to Tk Resize Events

# @@INCOMPLETE@@
 
# @@INCOMPLETE@@

Removing the DOS Shell Window with Windows Perl/Tk

# Start Python scripts without the annoying DOS window on win32
# Use extension ".pyw" on files - eg: "foo.pyw" instead of "foo.py"
# Or run programs using "pythonw.exe" rather than "python.exe"

Program: Small termcap program

# @@INCOMPLETE@@
# @@INCOMPLETE@@

Program: tkshufflepod

# @@INCOMPLETE@@
 
# @@INCOMPLETE@@