|
Python/FAQ/Пользовательский интерфейс
Материал из Wiki.crossplatform.ru
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@@
|