diff options
Diffstat (limited to 'test/scanners/python/pleac.in.py')
-rw-r--r-- | test/scanners/python/pleac.in.py | 11119 |
1 files changed, 0 insertions, 11119 deletions
diff --git a/test/scanners/python/pleac.in.py b/test/scanners/python/pleac.in.py deleted file mode 100644 index 6b9a79b..0000000 --- a/test/scanners/python/pleac.in.py +++ /dev/null @@ -1,11119 +0,0 @@ -# -*- python -*- -# vim:set ft=python: - -# @@PLEAC@@_NAME -# @@SKIP@@ Python - -# @@PLEAC@@_WEB -# @@SKIP@@ http://www.python.org - -# @@PLEAC@@_INTRO -# @@SKIP@@ The latest version of Python is 2.4 but users of 2.3 and 2.2 (and -# @@SKIP@@ in some cases earlier versions) can use the code herein. -# @@SKIP@@ Users of 2.2 and 2.3 should install or copy code from utils.py -# @@SKIP@@ (http://aima.cs.berkeley.edu/python/utils.py) -# @@SKIP@@ [the first section provides compatability code with 2.4] -# @@SKIP@@ Users of 2.2 should install optik (http://optik.sourceforge.com) -# @@SKIP@@ [for optparse and textwrap] -# @@SKIP@@ Where a 2.3 or 2.4 feature is unable to be replicated, an effort -# @@SKIP@@ has been made to provide a backward-compatible version in addition -# @@SKIP@@ to one using modern idioms. -# @@SKIP@@ Examples which translate the original Perl closely but which are -# @@SKIP@@ unPythonic are prefixed with a comment stating "DON'T DO THIS". -# @@SKIP@@ In some cases, it may be useful to know the techniques in these, -# @@SKIP@@ though it's a bad solution for the specific problem. - -# @@PLEAC@@_1.0 -#----------------------------- -mystr = "\n" # a newline character -mystr = r"\n" # two characters, \ and n -#----------------------------- -mystr = "Jon 'Maddog' Orwant" # literal single quote inside double quotes -mystr = 'Jon "Maddog" Orwant' # literal double quote inside single quotes -#----------------------------- -mystr = 'Jon \'Maddog\' Orwant' # escaped single quote -mystr = "Jon \"Maddog\" Orwant" # escaped double quote -#----------------------------- -mystr = """ -This is a multiline string literal -enclosed in triple double quotes. -""" -mystr = ''' -And this is a multiline string literal -enclosed in triple single quotes. -''' -#----------------------------- - -# @@PLEAC@@_1.1 -#----------------------------- - -# get a 5-char string, skip 3, then grab 2 8-char strings, then the rest -# Note that struct.unpack cannot use * for an unknown length. -# See http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/65224 -import struct -(lead, s1, s2), tail = struct.unpack("5s 3x 8s 8s", data[:24]), data[24:] - -# split at five-char boundaries -fivers = struct.unpack("5s" * (len(data)//5), data) -fivers = print [x[i*5:i*5+5] for i in range(len(x)/5)] - -# chop string into individual characters -chars = list(data) -#----------------------------- -mystr = "This is what you have" -# +012345678901234567890 Indexing forwards (left to right) -# 109876543210987654321- Indexing backwards (right to left) -# note that 0 means 10 or 20, etc. above - -first = mystr[0] # "T" -start = mystr[5:7] # "is" -rest = mystr[13:] # "you have" -last = mystr[-1] # "e" -end = mystr[-4:] # "have" -piece = mystr[-8:-5] # "you" -#----------------------------- -# Python strings are immutable. -# In general, you should just do piecemeal reallocation: -mystr = "This is what you have" -mystr = mystr[:5] + "wasn't" + mystr[7:] - -# Or replace and reallocate -mystr = "This is what you have" -mystr = mystr.replace(" is ", " wasn't ") - -# DON'T DO THIS: In-place modification could be done using character arrays -import array -mystr = array.array("c", "This is what you have") -mystr[5:7] = array.array("c", "wasn't") -# mystr is now array('c', "This wasn't what you have") - -# DON'T DO THIS: It could also be done using MutableString -from UserString import MutableString -mystr = MutableString("This is what you have") -mystr[-12:] = "ondrous" -# mystr is now "This is wondrous" -#----------------------------- -# you can test simple substrings with "in" (for regex matching see ch.6): -if txt in mystr[-10:]: - print "'%s' found in last 10 characters"%txt - -# Or use the startswith() and endswith() string methods: -if mystr.startswith(txt): - print "%s starts with %s."%(mystr, txt) -if mystr.endswith(txt): - print "%s ends with %s."%(mystr, txt) - -#----------------------------- - -# @@PLEAC@@_1.2 -#----------------------------- -# Introductory Note: quite a bit of this section is not terribly Pythonic -# as names must be set before being used. For instance, unless myvar has -# been previously defined, these next lines will all raise NameError: -myvar = myvar or some_default -myvar2 = myvar or some_default -myvar |= some_default # bitwise-or, not logical-or - for demo - -# The standard way of setting a default is often: -myvar = default_value -if some_condition: - pass # code which may set myvar to something else - -# if myvar is returned from a function and may be empty/None, then use: -myvar = somefunc() -if not myvar: - myvar = default_value - -# If you want a default value that can be overridden by the person calling -# your code, you can often wrap it in a function with a named parameter: -def myfunc(myvar="a"): - return myvar + "b" -print myfunc(), myfunc("c") -#=> ab cb - -# Note, though, that this won't work for mutable objects such as lists or -# dicts that are mutated in the function as the object is only created once -# and repeated calls to the same function will return the same object. This -# can be desired behaviour however - see section 10.3, for instance. -def myfunc(myvar=[]): - myvar.append("x") - return myvar -print myfunc(), myfunc() -#=> ['x'] ['x', 'x'] - -# You need to do: -def myfunc(myvar=None): - if myvar is None: - myvar = [] - myvar.append("x") - return myvar -print myfunc(), myfunc() -#=> ['x'] ['x'] - -#=== Perl Equivalencies start here -# use b if b is true, otherwise use c -a = b or c - -# as that is a little tricksy, the following may be preferred: -if b: - a = b -else: - a = c - -# set x to y unless x is already true -if not x: - x = y -#----------------------------- -# use b if b is defined, else c -try: - a = b -except NameError: - a = c -#----------------------------- -foo = bar or "DEFAULT VALUE" -#----------------------------- -# To get a user (for both UNIX and Windows), use: -import getpass -user = getpass.getuser() - -# DON'T DO THIS: find the user name on Unix systems -import os -user = os.environ.get("USER") -if user is None: - user = os.environ.get("LOGNAME") -#----------------------------- -if not starting_point: - starting_point = "Greenwich" -#----------------------------- -if not a: # copy only if empty - a = b - -if b: # assign b if nonempty, else c - a = b -else: - a = c -#----------------------------- - -# @@PLEAC@@_1.3 -#----------------------------- -v1, v2 = v2, v1 -#----------------------------- -# DON'T DO THIS: -temp = a -a = b -b = temp -#----------------------------- -a = "alpha" -b = "omega" -a, b = b, a # the first shall be last -- and versa vice -#----------------------------- -alpha, beta, production = "January March August".split() -alpha, beta, production = beta, production, alpha -#----------------------------- - -# @@PLEAC@@_1.4 -#----------------------------- -num = ord(char) -char = chr(num) -#----------------------------- -char = "%c" % num -print "Number %d is character %c" % (num, num) -print "Number %(n)d is character %(n)c" % {"n": num} -print "Number %(num)d is character %(num)c" % locals() -#=> Number 101 is character e -#----------------------------- -ascii_character_numbers = [ord(c) for c in "sample"] -print ascii_character_numbers -#=> [115, 97, 109, 112, 108, 101] - -word = "".join([chr(n) for n in ascii_character_numbers]) -word = "".join([chr(n) for n in [115, 97, 109, 112, 108, 101]]) -print word -#=> sample -#----------------------------- -hal = "HAL" -ibm = "".join([chr(ord(c)+1) for c in hal]) # add one to each ASCII value -print ibm -#=> IBM -#----------------------------- - -# @@PLEAC@@_1.5 -#----------------------------- -mylist = list(mystr) -#----------------------------- -for char in mystr: - pass # do something with char -#----------------------------- -mystr = "an apple a day" -uniq = sorted(set(mystr)) -print "unique chars are: '%s'" % "".join(uniq) -#=> unique chars are: ' adelnpy' -#----------------------------- -ascvals = [ord(c) for c in mystr] -print "total is %s for '%s'."%(sum(ascvals), mystr) -#=> total is 1248 for 'an apple a day'. -#----------------------------- -# sysv checksum -def checksum(myfile): - values = [ord(c) for line in myfile for c in line] - return sum(values)%(2**16) - 1 - -import fileinput -print checksum(fileinput.input()) # data from sys.stdin - -# Using a function means any iterable can be checksummed: -print checksum(open("C:/test.txt") # data from file -print checksum("sometext") # data from string -#----------------------------- -#!/usr/bin/python -# slowcat - emulate a s l o w line printer -# usage: slowcat [- DELAY] [files ...] -import sys, select -import re -DELAY = 1 -if re.match("^-\d+$",sys.argv[1]): - DELAY=-int(sys.argv[1]) - del sys.argv[1] -for ln in fileinput.input(): - for c in ln: - sys.stdout.write(c) - sys.stdout.flush() - select.select([],[],[], 0.005 * DELAY) -#----------------------------- - -# @@PLEAC@@_1.6 -#----------------------------- -# 2.3+ only -revchars = mystr[::-1] # extended slice - step is -1 -revwords = " ".join(mystr.split(" ")[::-1]) - -# pre 2.3 version: -mylist = list(mystr) -mylist.reverse() -revbytes = "".join(mylist) - -mylist = mystr.split() -mylist.reverse() -revwords = ' '.join(mylist) - -# Alternative version using reversed(): -revchars = "".join(reversed(mystr)) -revwords = " ".join(reversed(mystr.split(" "))) - -# reversed() makes an iterator, which means that the reversal -# happens as it is consumed. This means that "print reversed(mystr)" is not -# the same as mystr[::-1]. Standard usage is: -for char in reversed(mystr): - pass # ... do something -#----------------------------- -# 2.3+ only -word = "reviver" -is_palindrome = (word == word[::-1]) -#----------------------------- -# Generator version -def get_palindromes(fname): - for line in open(fname): - word = line.rstrip() - if len(word) > 5 and word == word[::-1]: - yield word -long_palindromes = list(get_palindromes("/usr/share/dict/words")) - -# Simpler old-style version using 2.2 string reversal -def rev_string(mystr): - mylist = list(mystr) - mylist.reverse() - return "".join(mylist) - -long_palindromes=[] -for line in open("/usr/share/dict/words"): - word = line.rstrip() - if len(word) > 5 and word == rev_string(word): - long_palindromes.append(word) -print long_palindromes -#----------------------------- - -# @@PLEAC@@_1.7 -#----------------------------- -mystr.expandtabs() -mystr.expandtabs(4) -#----------------------------- - -# @@PLEAC@@_1.8 -#----------------------------- -text = "I am %(rows)s high and %(cols)s long"%{"rows":24, "cols":80) -print text -#=> I am 24 high and 80 long - -rows, cols = 24, 80 -text = "I am %(rows)s high and %(cols)s long"%locals() -print text -#=> I am 24 high and 80 long -#----------------------------- -import re -print re.sub("\d+", lambda i: str(2 * int(i.group(0))), "I am 17 years old") -#=> I am 34 years old -#----------------------------- -# expand variables in text, but put an error message in -# if the variable isn't defined -class SafeDict(dict): - def __getitem__(self, key): - return self.get(key, "[No Variable: %s]"%key) - -hi = "Hello" -text = "%(hi)s and %(bye)s!"%SafeDict(locals()) -print text -#=> Hello and [No Variable: bye]! - -#If you don't need a particular error message, just use the Template class: -from string import Template -x = Template("$hi and $bye!") -hi = "Hello" -print x.safe_substitute(locals()) -#=> Hello and $bye! -print x.substitute(locals()) # will throw a KeyError - -#----------------------------- - -# @@PLEAC@@_1.9 -#----------------------------- -mystr = "bo peep".upper() # BO PEEP -mystr = mystr.lower() # bo peep -mystr = mystr.capitalize() # Bo peep -#----------------------------- -beast = "python" -caprest = beast.capitalize().swapcase() # pYTHON -#----------------------------- -print "thIS is a loNG liNE".title() -#=> This Is A Long Line -#----------------------------- -if a.upper() == b.upper(): - print "a and b are the same" -#----------------------------- -import random -def randcase_one(letter): - if random.randint(0,5): # True on 1, 2, 3, 4 - return letter.lower() - else: - return letter.upper() - -def randcase(myfile): - for line in myfile: - yield "".join(randcase_one(letter) for letter in line[:-1]) - -for line in randcase(myfile): - print line -#----------------------------- - -# @@PLEAC@@_1.10 -#----------------------------- -"I have %d guanacos." % (n + 1) -print "I have", n+1, "guanacos." -#----------------------------- -#Python templates disallow in-string calculations (see PEP 292) -from string import Template - -email_template = Template("""\ -To: $address -From: Your Bank -CC: $cc_number -Date: $date - -Dear $name, - -Today you bounced check number $checknum to us. -Your account is now closed. - -Sincerely, -the management -""") - -import random -import datetime - -person = {"address":"Joe@somewhere.com", - "name": "Joe", - "cc_number" : 1234567890, - "checknum" : 500+random.randint(0,99)} - -print email_template.substitute(person, date=datetime.date.today()) -#----------------------------- - -# @@PLEAC@@_1.11 -#----------------------------- -# indenting here documents -# -# in python multiline strings can be used as here documents -var = """ - your text - goes here - """ - -# using regular expressions -import re -re_leading_blanks = re.compile("^\s+",re.MULTILINE) -var1 = re_leading_blanks.sub("",var)[:-1] - -# using string methods -# split into lines, use every line except first and last, left strip and rejoin. -var2 = "\n".join([line.lstrip() for line in var.split("\n")[1:-1]]) - -poem = """ - Here's your poem: - Now far ahead the Road has gone, - And I must follow, if I can, - Pursuing it with eager feet, - Until it joins some larger way - Where many paths and errand meet. - And whither then? I cannot say. - --Bilbo in /usr/src/perl/pp_ctl.c - """ - -import textwrap -print textwrap.dedent(poem)[1:-1] -#----------------------------- - - -# @@PLEAC@@_1.12 -#----------------------------- -from textwrap import wrap -output = wrap(para, - initial_indent=leadtab - subsequent_indent=nexttab) -#----------------------------- -#!/usr/bin/env python -# wrapdemo - show how textwrap works - -txt = """\ -Folding and splicing is the work of an editor, -not a mere collection of silicon -and -mobile electrons! -""" - -from textwrap import TextWrapper - -wrapper = TextWrapper(width=20, - initial_indent=" "*4, - subsequent_indent=" "*2) - -print "0123456789" * 2 -print wrapper.fill(txt) - -#----------------------------- -"""Expected result: - -01234567890123456789 - Folding and - splicing is the - work of an editor, - not a mere - collection of - silicon and mobile - electrons! -""" - -#----------------------------- -# merge multiple lines into one, then wrap one long line - -from textwrap import fill -import fileinput - -print fill("".join(fileinput.input())) - -#----------------------------- -# Term::ReadKey::GetTerminalSize() isn't in the Perl standard library. -# It isn't in the Python standard library either. Michael Hudson's -# recipe from python-list #530228 is shown here. -# (http://aspn.activestate.com/ASPN/Mail/Message/python-list/530228) -# Be aware that this will work on Unix but not on Windows. - -from termwrap import wrap -import struct, fcntl -def getheightwidth(): - height, width = struct.unpack( - "hhhh", fcntl.ioctl(0, TERMIOS.TIOCGWINSZ ,"\000"*8))[0:2] - return height, width - -# PERL <>, $/, $\ emulation -import fileinput -import re - -_, width = getheightwidth() -for para in re.split(r"\n{2,}", "".join(fileinput.input())): - print fill(para, width) - - -# @@PLEAC@@_1.13 -#----------------------------- -mystr = '''Mom said, "Don't do that."''' #" -re.sub("['\"]", lambda i: "\\" + i.group(0), mystr) -re.sub("[A-Z]", lambda i: "\\" + i.group(0), mystr) -re.sub("\W", lambda i: "\\" + i.group(0), "is a test!") # no function like quotemeta? - - -# @@PLEAC@@_1.14 -#----------------------------- -mystr = mystr.lstrip() # left -mystr = mystr.rstrip() # right -mystr = mystr.strip() # both ends - - -# @@PLEAC@@_1.15 -#----------------------------- -import csv -def parse_csv(line): - reader = csv.reader([line], escapechar='\\') - return reader.next() - -line = '''XYZZY,"","O'Reilly, Inc","Wall, Larry","a \\"glug\\" bit,",5,"Error, Core Dumped,",''' #" - -fields = parse_csv(line) - -for i, field in enumerate(fields): - print "%d : %s" % (i, field) - -# pre-2.3 version of parse_csv -import re -def parse_csv(text): - pattern = re.compile('''"([^"\\\]*(?:\\\.[^"\\\]*)*)",?|([^,]+),?|,''') - mylist = ["".join(elem) - for elem in re.findall(pattern, text)] - if text[-1] == ",": - mylist += [''] - return mylist - -# cvs.reader is meant to work for many lines, something like: -# (NB: in Python default, quotechar is *not* escaped by backslash, -# but doubled instead. That's what Excel does.) -for fields in cvs.reader(lines, dialect="some"): - for num, field in enumerate(fields): - print num, ":", field -#----------------------------- - -# @@PLEAC@@_1.16 -#----------------------------- -def soundex(name, len=4): - """ soundex module conforming to Knuth's algorithm - implementation 2000-12-24 by Gregory Jorgensen - public domain - """ - - # digits holds the soundex values for the alphabet - digits = '01230120022455012623010202' - sndx = '' - fc = '' - - # translate alpha chars in name to soundex digits - for c in name.upper(): - if c.isalpha(): - if not fc: - fc = c # remember first letter - d = digits[ord(c)-ord('A')] - # duplicate consecutive soundex digits are skipped - if not sndx or (d != sndx[-1]): - sndx += d - - # replace first digit with first alpha character - sndx = fc + sndx[1:] - - # remove all 0s from the soundex code - sndx = sndx.replace('0','') - - # return soundex code padded to len characters - return (sndx + (len * '0'))[:len] - -user = raw_input("Lookup user: ") -if user == "": - raise SystemExit - -name_code = soundex(user) -for line in open("/etc/passwd"): - line = line.split(":") - for piece in line[4].split(): - if name_code == soundex(piece): - print "%s: %s\n" % line[0], line[4]) -#----------------------------- - -# @@PLEAC@@_1.17 -#----------------------------- -import sys, fileinput, re - -data = """\ -analysed => analyzed -built-in => builtin -chastized => chastised -commandline => command-line -de-allocate => deallocate -dropin => drop-in -hardcode => hard-code -meta-data => metadata -multicharacter => multi-character -multiway => multi-way -non-empty => nonempty -non-profit => nonprofit -non-trappable => nontrappable -pre-define => predefine -preextend => pre-extend -re-compiling => recompiling -reenter => re-enter -turnkey => turn-key -""" -mydict = {} -for line in data.split("\n"): - if not line.strip(): - continue - k, v = [word.strip() for word in line.split("=>")] - mydict[k] = v -pattern_text = "(" + "|".join([re.escape(word) for word in mydict.keys()]) + ")" -pattern = re.compile(pattern_text) - -args = sys.argv[1:] -verbose = 0 -if args and args[0] == "-v": - verbose = 1 - args = args[1:] - -if not args: - sys.stderr.write("%s: Reading from stdin\n" % sys.argv[0]) - -for line in fileinput.input(args, inplace=1, backup=".orig"): - output = "" - pos = 0 - while True: - match = pattern.search(line, pos) - if not match: - output += line[pos:] - break - output += line[pos:match.start(0)] + mydict[match.group(1)] - pos = match.end(0) - sys.stdout.write(output) -#----------------------------- - -# @@PLEAC@@_1.18 -#----------------------------- -#!/usr/bin/python -# psgrep - print selected lines of ps output by -# compiling user queries into code. -# -# examples : -# psgrep "uid<10" -import sys, os, re - -class PsLineMatch: - # each field from the PS header - fieldnames = ("flags","uid","pid","ppid","pri","nice","size", \ - "rss","wchan","stat","tty","time","command") - numeric_fields = ("flags","uid","pid","ppid","pri","nice","size","rss") - def __init__(self): - self._fields = {} - - def new_line(self, ln): - self._ln = ln.rstrip() - # ps header for option "wwaxl" (different than in the perl code) - """ - F UID PID PPID PRI NI VSZ RSS WCHAN STAT TTY TIME COMMAND" - 004 0 1 0 15 0 448 236 schedu S ? 0:07 init" - . . . . . . . . . . . . . - """ - # because only the last entry might contain blanks, splitting - # is safe - data = self._ln.split(None,12) - for fn, elem in zip(self.fieldnames, data): - if fn in self.numeric_fields: # make numbers integer - self._fields[fn] = int(elem) - else: - self._fields[fn] = elem - - def set_query(self, args): - # assume args: "uid==500", "command ~ ^wm" - conds=[] - m = re.compile("(\w+)([=<>]+)(.+)") - for a in args: - try: - (field,op,val) = m.match(a).groups() - except: - print "can't understand query \"%s\"" % (a) - raise SystemExit - if field in self.numeric_fields: - conds.append(a) - else: - conds.append("%s%s'%s'",(field,op,val)) - self._desirable = compile("(("+")and(".join(conds)+"))", "<string>","eval") - - def is_desirable(self): - return eval(self._desirable, {}, self._fields) - - def __str__(self): - # to allow "print". - return self._ln - -if len(sys.argv)<=1: - print """usage: %s criterion ... - Each criterion is a Perl expression involving: - %s - All criteria must be met for a line to be printed.""" \ - % (sys.argv[0], " ".join(PsLineMatch().fieldnames)) - raise SystemExit - -psln = PsLineMatch() -psln.set_query(sys.argv[1:]) -p = os.popen("ps wwaxl") -print p.readline()[:-1] # emit header line -for ln in p.readlines(): - psln.new_line(ln) - if psln.is_desirable(): - print psln -p.close() - -# alternatively one could consider every argument being a string and -# support wildcards: "uid==500" "command~^wm" by means of re, but this -# does not show dynamic python code generation, although re.compile -# also precompiles. -#----------------------------- - - -# @@PLEAC@@_2.1 -#----------------------------- -# The standard way of validating numbers is to convert them and catch -# an exception on failure - -try: - myfloat = float(mystr) - print "is a decimal number" -except TypeError: - print "is not a decimal number" - -try: - myint = int(mystr) - print "is an integer" -except TypeError: - print "is not an integer" - -# DON'T DO THIS. Explicit checking is prone to errors: -if mystr.isdigit(): # Fails on "+4" - print 'is a positive integer' -else: - print 'is not' - -if re.match("[+-]?\d+$", mystr): # Fails on "- 1" - print 'is an integer' -else: - print 'is not' - -if re.match("-?(?:\d+(?:\.\d*)?|\.\d+)$", mystr): # Opaque, and fails on "- 1" - print 'is a decimal number' -else: - print 'is not' - -#----------------------------- - -# @@PLEAC@@_2.2 -#----------------------------- -# equal(num1, num2, accuracy) : returns true if num1 and num2 are -# equal to accuracy number of decimal places - -def equal(num1, num2, accuracy): - return abs(num1 - num2) < 10**(-accuracy) -#----------------------------- -from __future__ import division # use / for float div and // for int div - -wage = 536 # $5.36/hour -week = 40 * wage # $214.40 -print "One week's wage is: $%.2f" % (week/100) -#=> One week's wage is: $214.40 -#----------------------------- - -# @@PLEAC@@_2.3 -#----------------------------- -rounded = round(num) # rounds to integer -#----------------------------- -a = 0.255 -b = "%.2f" % a -print "Unrounded: %f\nRounded: %s" % (a, b) -print "Unrounded: %f\nRounded: %.2f" % (a, a) -#=> Unrounded: 0.255000 -#=> Rounded: 0.26 -#=> Unrounded: 0.255000 -#=> Rounded: 0.26 -#----------------------------- -from math import floor, ceil - -print "number\tint\tfloor\tceil" -a = [3.3, 3.5, 3.7, -3.3] -for n in a: - print "% .1f\t% .1f\t% .1f\t% .1f" % (n, int(n), floor(n), ceil(n)) -#=> number int floor ceil -#=> 3.3 3.0 3.0 4.0 -#=> 3.5 3.0 3.0 4.0 -#=> 3.7 3.0 3.0 4.0 -#=> -3.3 -3.0 -4.0 -3.0 -#----------------------------- - -# @@PLEAC@@_2.4 -#----------------------------- -# To convert a string in any base up to base 36, use the optional arg to int(): -num = int('0110110', 2) # num is 54 - -# To convert an int to an string representation in another base, you could use -# <http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/111286>: -import baseconvert -def dec2bin(i): - return baseconvert.baseconvert(i, baseconvert.BASE10, baseconvert.BASE2) - -binstr = dec2bin(54) # binstr is 110110 -#----------------------------- - -# @@PLEAC@@_2.5 -#----------------------------- -for i in range(x,y): - pass # i is set to every integer from x to y, excluding y - -for i in range(x, y, 7): - pass # i is set to every integer from x to y, stepsize = 7 - -print "Infancy is:", -for i in range(0,3): - print i, -print - -print "Toddling is:", -for i in range(3,5): - print i, -print - -# DON'T DO THIS: -print "Childhood is:", -i = 5 -while i <= 12: - print i - i += 1 - -#=> Infancy is: 0 1 2 -#=> Toddling is: 3 4 -#=> Childhood is: 5 6 7 8 9 10 11 12 -#----------------------------- - -# @@PLEAC@@_2.6 -#----------------------------- -# See http://www.faqts.com/knowledge_base/view.phtml/aid/4442 -# for a module that does this -#----------------------------- - -# @@PLEAC@@_2.7 -#----------------------------- -import random # use help(random) to see the (large) list of funcs - -rand = random.randint(x, y) -#----------------------------- -rand = random.randint(25, 76) -print rand -#----------------------------- -elt = random.choice(mylist) -#----------------------------- -import string -chars = string.letters + string.digits + "!@$%^&*" -password = "".join([random.choice(chars) for i in range(8)]) -#----------------------------- - -# @@PLEAC@@_2.8 -#----------------------------- -# Changes the default RNG -random.seed() - -# Or you can create independent RNGs -gen1 = random.Random(6) -gen2 = random.Random(6) -gen3 = random.Random(10) -a1, b1 = gen1.random(), gen1.random() -a2, b2 = gen2.random(), gen2.random() -a3, b3 = gen3.random(), gen3.random() -# a1 == a2 and b1 == b2 -#----------------------------- - -# @@PLEAC@@_2.9 -#----------------------------- -# see http://www.sbc.su.se/~per/crng/ or http://www.frohne.westhost.com/rv11reference.htm -#----------------------------- - -# @@PLEAC@@_2.10 -#----------------------------- -import random -mean = 25 -sdev = 2 -salary = random.gauss(mean, sdev) -print "You have been hired at %.2f" % salary -#----------------------------- - -# @@PLEAC@@_2.11 -#----------------------------- -radians = math.radians(degrees) -degrees = math.degrees(radians) - -# pre-2.3: -from __future__ import division -import math -def deg2rad(degrees): - return (degrees / 180) * math.pi -def rad2deg(radians): - return (radians / math.pi) * 180 -#----------------------------- -# Use deg2rad instead of math.radians if you have pre-2.3 Python. -import math -def degree_sine(degrees): - radians = math.radians(degrees) - return math.sin(radians) -#----------------------------- - -# @@PLEAC@@_2.12 -#----------------------------- -import math - -# DON'T DO THIS. Use math.tan() instead. -def tan(theta): - return math.sin(theta) / math.cos(theta) -#---------------- -# NOTE: this sets y to 16331239353195370.0 -try: - y = math.tan(math.pi/2) -except ValueError: - y = None -#----------------------------- - -# @@PLEAC@@_2.13 -#----------------------------- -import math -log_e = math.log(VALUE) -#----------------------------- -log_10 = math.log10(VALUE) -#----------------------------- -def log_base(base, value): - return math.log(value) / math.log(base) -#----------------------------- -# log_base defined as above -answer = log_base(10, 10000) -print "log10(10,000) =", answer -#=> log10(10,000) = 4.0 -#----------------------------- - -# @@PLEAC@@_2.14 -#----------------------------- -# NOTE: must have NumPy installed. See -# http://www.pfdubois.com/numpy/ - -import Numeric -a = Numeric.array( ((3, 2, 3), - (5, 9, 8) ), "d") -b = Numeric.array( ((4, 7), - (9, 3), - (8, 1) ), "d") -c = Numeric.matrixmultiply(a, b) - -print c -#=> [[ 54. 30.] -#=> [ 165. 70.]] - -print a.shape, b.shape, c.shape -#=> (2, 3) (3, 2) (2, 2) -#----------------------------- - -# @@PLEAC@@_2.15 -#----------------------------- -a = 3+5j -b = 2-2j -c = a * b -print "c =", c -#=> c = (16+4j) - -print c.real, c.imag, c.conjugate() -#=> 16.0 4.0 (16-4j) -#----------------------------- -import cmath -print cmath.sqrt(3+4j) -#=> (2+1j) -#----------------------------- - -# @@PLEAC@@_2.16 -#----------------------------- -number = int(hexadecimal, 16) -number = int(octal, 8) -s = hex(number) -s = oct(number) - -num = raw_input("Gimme a number in decimal, octal, or hex: ").rstrip() -if num.startswith("0x"): - num = int(num[2:], 16) -elif num.startswith("0"): - num = int(num[1:], 8) -else: - num = int(num) -print "%(num)d %(num)x %(num)o\n" % { "num": num } -#----------------------------- - - -# @@PLEAC@@_2.17 -#----------------------------- -def commify(amount): - amount = str(amount) - firstcomma = len(amount)%3 or 3 # set to 3 if would make a leading comma - first, rest = amount[:firstcomma], amount[firstcomma:] - segments = [first] + [rest[i:i+3] for i in range(0, len(rest), 3)] - return ",".join(segments) - -print commify(12345678) -#=> 12,345,678 - -# DON'T DO THIS. It works on 2.3+ only and is slower and less straightforward -# than the non-regex version above. -import re -def commify(amount): - amount = str(amount) - amount = amount[::-1] - amount = re.sub(r"(\d\d\d)(?=\d)(?!\d*\.)", r"\1,", amount) - return amount[::-1] - -# @@PLEAC@@_2.18 -# Printing Correct Plurals -#----------------------------- -def pluralise(value, root, singular="", plural="s"): - if value == 1: - return root + singular - else: - return root + plural - -print "It took", duration, pluralise(duration, 'hour') - -print "%d %s %s enough." % (duration, - pluralise(duration, 'hour'), - pluralise(duration, '', 'is', 'are')) -#----------------------------- -import re -def noun_plural(word): - endings = [("ss", "sses"), - ("([psc]h)", r"\1es"), - ("z", "zes"), - ("ff", "ffs"), - ("f", "ves"), - ("ey", "eys"), - ("y", "ies"), - ("ix", "ices"), - ("([sx])", r"\1es"), - ("", "s")] - for singular, plural in endings: - ret, found = re.subn("%s$"%singular, plural, word) - if found: - return ret - -verb_singular = noun_plural; # make function alias -#----------------------------- - -# @@PLEAC@@_2.19 -# Program: Calculating Prime Factors -#----------------------------- -#% bigfact 8 9 96 2178 -#8 2**3 -# -#9 3**2 -# -#96 2**5 3 -# -#2178 2 3**2 11**2 -#----------------------------- -#% bigfact 239322000000000000000000 -#239322000000000000000000 2**19 3 5**18 39887 -# -# -#% bigfact 25000000000000000000000000 -#25000000000000000000000000 2**24 5**26 -#----------------------------- -import sys - -def factorise(num): - factors = {} - orig = num - print num, '\t', - - # we take advantage of the fact that (i +1)**2 = i**2 + 2*i +1 - i, sqi = 2, 4 - while sqi <= num: - while not num%i: - num /= i - factors[i] = factors.get(i, 0) + 1 - - sqi += 2*i + 1 - i += 1 - - if num != 1 and num != orig: - factors[num] = factors.get(num, 0) + 1 - - if not factors: - print "PRIME" - - for factor in sorted(factors): - if factor: - tmp = str(factor) - if factors[factor]>1: tmp += "**" + str(factors[factor]) - print tmp, - print - -#-------- -if __name__ == '__main__': - if len(sys.argv) == 1: - print "Usage:", sys.argv[0], " number [number, ]" - else: - for strnum in sys.argv[1:]: - try: - num = int(strnum) - factorise(num) - except ValueError: - print strnum, "is not an integer" -#----------------------------- -# A more Pythonic variant (which separates calculation from printing): -def format_factor(base, exponent): - if exponent > 1: - return "%s**%s"%(base, exponent) - return str(base) - -def factorise(num): - factors = {} - orig = num - - # we take advantage of the fact that (i+1)**2 = i**2 + 2*i +1 - i, sqi = 2, 4 - while sqi <= num: - while not num%i: - num /= i - factors[i] = factors.get(i, 0) + 1 - sqi += 2*i + 1 - i += 1 - - if num not in (1, orig): - factors[num] = factors.get(num, 0) + 1 - - if not factors: - return ["PRIME"] - - out = [format_factor(base, exponent) - for base, exponent in sorted(factors.items())] - return out - -def print_factors(value): - try: - num = int(value) - if num != float(value): - raise ValueError - except (ValueError, TypeError): - raise ValueError("Can only factorise an integer") - factors = factorise(num) - print num, "\t", " ".join(factors) - -# @@PLEAC@@_3.0 -#----------------------------- -#introduction -# There are three common ways of manipulating dates in Python -# mxDateTime - a popular third-party module (not discussed here) -# time - a fairly low-level standard library module -# datetime - a new library module for Python 2.3 and used for most of these samples -# (I will use full names to show which module they are in, but you can also use -# from datetime import datetime, timedelta and so on for convenience) - -import time -import datetime - -print "Today is day", time.localtime()[7], "of the current year" -# Today is day 218 of the current year - -today = datetime.date.today() -print "Today is day", today.timetuple()[7], "of ", today.year -# Today is day 218 of 2003 - -print "Today is day", today.strftime("%j"), "of the current year" -# Today is day 218 of the current year - - -# @@PLEAC@@_3.1 -#----------------------------- -# Finding todays date - -today = datetime.date.today() -print "The date is", today -#=> The date is 2003-08-06 - -# the function strftime() (string-format time) produces nice formatting -# All codes are detailed at http://www.python.org/doc/current/lib/module-time.html -print t.strftime("four-digit year: %Y, two-digit year: %y, month: %m, day: %d") -#=> four-digit year: 2003, two-digit year: 03, month: 08, day: 06 - - -# @@PLEAC@@_3.2 -#----------------------------- -# Converting DMYHMS to Epoch Seconds -# To work with Epoch Seconds, you need to use the time module - -# For the local timezone -t = datetime.datetime.now() -print "Epoch Seconds:", time.mktime(t.timetuple()) -#=> Epoch Seconds: 1060199000.0 - -# For UTC -t = datetime.datetime.utcnow() -print "Epoch Seconds:", time.mktime(t.timetuple()) -#=> Epoch Seconds: 1060195503.0 - - -# @@PLEAC@@_3.3 -#----------------------------- -# Converting Epoch Seconds to DMYHMS - -now = datetime.datetime.fromtimestamp(EpochSeconds) -#or use datetime.datetime.utcfromtimestamp() -print now -#=> datetime.datetime(2003, 8, 6, 20, 43, 20) -print now.ctime() -#=> Wed Aug 6 20:43:20 2003 - -# or with the time module -oldtimetuple = time.localtime(EpochSeconds) -# oldtimetuple contains (year, month, day, hour, minute, second, weekday, yearday, daylightSavingAdjustment) -print oldtimetuple -#=> (2003, 8, 6, 20, 43, 20, 2, 218, 1) - - -# @@PLEAC@@_3.4 -#----------------------------- -# Adding to or Subtracting from a Date -# Use the rather nice datetime.timedelta objects - -now = datetime.date(2003, 8, 6) -difference1 = datetime.timedelta(days=1) -difference2 = datetime.timedelta(weeks=-2) - -print "One day in the future is:", now + difference1 -#=> One day in the future is: 2003-08-07 - -print "Two weeks in the past is:", now + difference2 -#=> Two weeks in the past is: 2003-07-23 - -print datetime.date(2003, 8, 6) - datetime.date(2000, 8, 6) -#=> 1095 days, 0:00:00 - -#----------------------------- -birthtime = datetime.datetime(1973, 01, 18, 3, 45, 50) # 1973-01-18 03:45:50 - -interval = datetime.timedelta(seconds=5, minutes=17, hours=2, days=55) -then = birthtime + interval - -print "Then is", then.ctime() -#=> Then is Wed Mar 14 06:02:55 1973 - -print "Then is", then.strftime("%A %B %d %I:%M:%S %p %Y") -#=> Then is Wednesday March 14 06:02:55 AM 1973 - -#----------------------------- -when = datetime.datetime(1973, 1, 18) + datetime.timedelta(days=55) -print "Nat was 55 days old on:", when.strftime("%m/%d/%Y").lstrip("0") -#=> Nat was 55 days old on: 3/14/1973 - - -# @@PLEAC@@_3.5 -#----------------------------- -# Dates produce timedeltas when subtracted. - -diff = date2 - date1 -diff = datetime.date(year1, month1, day1) - datetime.date(year2, month2, day2) -#----------------------------- - -bree = datetime.datetime(1981, 6, 16, 4, 35, 25) -nat = datetime.datetime(1973, 1, 18, 3, 45, 50) - -difference = bree - nat -print "There were", difference, "minutes between Nat and Bree" -#=> There were 3071 days, 0:49:35 between Nat and Bree - -weeks, days = divmod(difference.days, 7) - -minutes, seconds = divmod(difference.seconds, 60) -hours, minutes = divmod(minutes, 60) - -print "%d weeks, %d days, %d:%d:%d" % (weeks, days, hours, minutes, seconds) -#=> 438 weeks, 5 days, 0:49:35 - -#----------------------------- -print "There were", difference.days, "days between Bree and Nat." -#=> There were 3071 days between bree and nat - - -# @@PLEAC@@_3.6 -#----------------------------- -# Day in a Week/Month/Year or Week Number - -when = datetime.date(1981, 6, 16) - -print "16/6/1981 was:" -print when.strftime("Day %w of the week (a %A). Day %d of the month (%B).") -print when.strftime("Day %j of the year (%Y), in week %W of the year.") - -#=> 16/6/1981 was: -#=> Day 2 of the week (a Tuesday). Day 16 of the month (June). -#=> Day 167 of the year (1981), in week 24 of the year. - - -# @@PLEAC@@_3.7 -#----------------------------- -# Parsing Dates and Times from Strings - -time.strptime("Tue Jun 16 20:18:03 1981") -# (1981, 6, 16, 20, 18, 3, 1, 167, -1) - -time.strptime("16/6/1981", "%d/%m/%Y") -# (1981, 6, 16, 0, 0, 0, 1, 167, -1) -# strptime() can use any of the formatting codes from time.strftime() - -# The easiest way to convert this to a datetime seems to be; -now = datetime.datetime(*time.strptime("16/6/1981", "%d/%m/%Y")[0:5]) -# the '*' operator unpacks the tuple, producing the argument list. - - -# @@PLEAC@@_3.8 -#----------------------------- -# Printing a Date -# Use datetime.strftime() - see helpfiles in distro or at python.org - -print datetime.datetime.now().strftime("The date is %A (%a) %d/%m/%Y") -#=> The date is Friday (Fri) 08/08/2003 - -# @@PLEAC@@_3.9 -#----------------------------- -# High Resolution Timers - -t1 = time.clock() -# Do Stuff Here -t2 = time.clock() -print t2 - t1 - -# 2.27236813618 -# Accuracy will depend on platform and OS, -# but time.clock() uses the most accurate timer it can - -time.clock(); time.clock() -# 174485.51365466841 -# 174485.55702610247 - -#----------------------------- -# Also useful; -import timeit -code = '[x for x in range(10) if x % 2 == 0]' -eval(code) -# [0, 2, 4, 6, 8] - -t = timeit.Timer(code) -print "10,000 repeats of that code takes:", t.timeit(10000), "seconds" -print "1,000,000 repeats of that code takes:", t.timeit(), "seconds" - -# 10,000 repeats of that code takes: 0.128238644856 seconds -# 1,000,000 repeats of that code takes: 12.5396490336 seconds - -#----------------------------- -import timeit -code = 'import random; l = random.sample(xrange(10000000), 1000); l.sort()' -t = timeit.Timer(code) - -print "Create a list of a thousand random numbers. Sort the list. Repeated a thousand times." -print "Average Time:", t.timeit(1000) / 1000 -# Time taken: 5.24391507859 - - -# @@PLEAC@@_3.10 -#----------------------------- -# Short Sleeps - -seconds = 3.1 -time.sleep(seconds) -print "boo" - -# @@PLEAC@@_3.11 -#----------------------------- -# Program HopDelta -# Save a raw email to disk and run "python hopdelta.py FILE" -# and it will process the headers and show the time taken -# for each server hop (nb: if server times are wrong, negative dates -# might appear in the output). - -import datetime, email, email.Utils -import os, sys, time - -def extract_date(hop): - # According to RFC822, the date will be prefixed with - # a semi-colon, and is the last part of a received - # header. - date_string = hop[hop.find(';')+2:] - date_string = date_string.strip() - time_tuple = email.Utils.parsedate(date_string) - - # convert time_tuple to datetime - EpochSeconds = time.mktime(time_tuple) - dt = datetime.datetime.fromtimestamp(EpochSeconds) - return dt - -def process(filename): - # Main email file processing - # read the headers and process them - f = file(filename, 'rb') - msg = email.message_from_file(f) - - hops = msg.get_all('received') - - # in reverse order, get the server(s) and date/time involved - hops.reverse() - results = [] - for hop in hops: - hop = hop.lower() - - if hop.startswith('by'): # 'Received: by' line - sender = "start" - receiver = hop[3:hop.find(' ',3)] - date = extract_date(hop) - - else: # 'Received: from' line - sender = hop[5:hop.find(' ',5)] - by = hop.find('by ')+3 - receiver = hop[by:hop.find(' ', by)] - date = extract_date(hop) - - results.append((sender, receiver, date)) - output(results) - -def output(results): - print "Sender, Recipient, Time, Delta" - print - previous_dt = delta = 0 - for (sender, receiver, date) in results: - if previous_dt: - delta = date - previous_dt - - print "%s, %s, %s, %s" % (sender, - receiver, - date.strftime("%Y/%d/%m %H:%M:%S"), - delta) - print - previous_dt = date - -def main(): - # Perform some basic argument checking - if len(sys.argv) != 2: - print "Usage: mailhop.py FILENAME" - - else: - filename = sys.argv[1] - if os.path.isfile(filename): - process(filename) - else: - print filename, "doesn't seem to be a valid file." - -if __name__ == '__main__': - main() - - -# @@PLEAC@@_4.0 -#----------------------------- -# Python does not automatically flatten lists, in other words -# in the following, non-nested contains four elements and -# nested contains three elements, the third element of which -# is itself a list containing two elements: -non_nested = ["this", "that", "the", "other"] -nested = ["this", "that", ["the", "other"]] -#----------------------------- -tune = ["The", "Star-Spangled", "Banner"] -#----------------------------- - -# @@PLEAC@@_4.1 -#----------------------------- -a = ["quick", "brown", "fox"] -a = "Why are you teasing me?".split() - -text = """ - The boy stood on the burning deck, - It was as hot as glass. -""" -lines = [line.lstrip() for line in text.strip().split("\n")] -#----------------------------- -biglist = [line.rstrip() for line in open("mydatafile")] -#----------------------------- -banner = "The Mines of Moria" -banner = 'The Mines of Moria' -#----------------------------- -name = "Gandalf" -banner = "Speak, " + name + ", and enter!" -banner = "Speak, %s, and welcome!" % name -#----------------------------- -his_host = "www.python.org" -import os -host_info = os.popen("nslookup " + his_host).read() - -# NOTE: not really relevant to Python (no magic '$$' variable) -python_info = os.popen("ps %d" % os.getpid()).read() -shell_info = os.popen("ps $$").read() -#----------------------------- -# NOTE: not really relevant to Python (no automatic interpolation) -banner = ["Costs", "only", "$4.95"] -banner = "Costs only $4.95".split() -#----------------------------- -brax = """ ' " ( ) < > { } [ ] """.split() #""" -brax = list("""'"()<>{}[]""") #""" -rings = '''They're "Nenya Narya Vilya"'''.split() #''' -tags = 'LI TABLE TR TD A IMG H1 P'.split() -sample = r'The backslash (\) is often used in regular expressions.'.split() - -#----------------------------- -banner = "The backslash (\\) is often used in regular expressions.".split() -#----------------------------- -ships = u"Niña Pinta Santa MarÃa".split() # WRONG (only three ships) -ships = [u"Niña", u"Pinta", u"Santa MarÃa"] # right -#----------------------------- - -# @@PLEAC@@_4.2 -#----------------------------- -def commify_series(args): - n = len(args) - if n == 0: - return "" - elif n == 1: - return args[0] - elif n == 2: - return args[0] + " and " + args[1] - return ", ".join(args[:-1]) + ", and " + args[-1] - -commify_series([]) -commify_series(["red"]) -commify_series(["red", "yellow"]) -commify_series(["red", "yellow", "green"]) -#----------------------------- -mylist = ["red", "yellow", "green"] -print "I have", mylist, "marbles." -print "I have", " ".join(mylist), "marbles." -#=> I have ['red', 'yellow', 'green'] marbles. -#=> I have red yellow green marbles. - -#----------------------------- -#!/usr/bin/env python -# commify_series - show proper comma insertion in list output -data = ( - ( 'just one thing', ), - ( 'Mutt Jeff'.split() ), - ( 'Peter Paul Mary'.split() ), - ( 'To our parents', 'Mother Theresa', 'God' ), - ( 'pastrami', 'ham and cheese', 'peanut butter and jelly', 'tuna' ), - ( 'recycle tired, old phrases', 'ponder big, happy thoughts' ), - ( 'recycle tired, old phrases', - 'ponder big, happy thoughts', - 'sleep and dream peacefully' ), - ) - -def commify_series(terms): - for term in terms: - if "," in term: - sepchar = "; " - break - else: - sepchar = ", " - - n = len(terms) - if n == 0: - return "" - elif n == 1: - return terms[0] - elif n == 2: - return " and ".join(terms) - return "%s%sand %s" % (sepchar.join(terms[:-1]), sepchar, terms[-1]) - -for item in data: - print "The list is: %s." % commify_series(item) - -#=> The list is: just one thing. -#=> The list is: Mutt and Jeff. -#=> The list is: Peter, Paul, and Mary. -#=> The list is: To our parents, Mother Theresa, and God. -#=> The list is: pastrami, ham and cheese, peanut butter and jelly, and tuna. -#=> The list is: recycle tired, old phrases and ponder big, happy thoughts. -#=> The list is: recycle tired, old phrases; ponder big, happy thoughts; and -# sleep and dream peacefully. -#----------------------------- - -# @@PLEAC@@_4.3 -#----------------------------- -# Python allocates more space than is necessary every time a list needs to -# grow and only shrinks lists when more than half the available space is -# unused. This means that adding or removing an element will in most cases -# not force a reallocation. - -del mylist[size:] # shrink mylist -mylist += [None] * size # grow mylist by appending 'size' None elements - -# To add an element to the end of a list, use the append method: -mylist.append(4) - -# To insert an element, use the insert method: -mylist.insert(0, 10) # Insert 10 at the beginning of the list - -# To extend one list with the contents of another, use the extend method: -list2 = [1,2,3] -mylist.extend(list2) - -# To insert the contents of one list into another, overwriting zero or -# more elements, specify a slice: -mylist[1:1] = list2 # Don't overwrite anything; grow mylist if needed -mylist[2:3] = list2 # Overwrite mylist[2] and grow mylist if needed - -# To remove one element from the middle of a list: -# To remove elements from the middle of a list: -del mylist[idx1:idx2] # 0 or more -x = mylist.pop(idx) # remove mylist[idx] and assign it to x - -# You cannot assign to or get a non-existent element: -# >>> x = [] -# >>> x[4] = 5 -# -# Traceback (most recent call last): -# File "<pyshell#1>", line 1, in -toplevel- -# x[4] = 5 -# IndexError: list assignment index out of range -# -# >>> print x[1000] -# -# Traceback (most recent call last): -# File "<pyshell#16>", line 1, in -toplevel- -# print x[1000] -# IndexError: list index out of range -#----------------------------- -def what_about_that_list(terms): - print "The list now has", len(terms), "elements." - print "The index of the last element is", len(terms)-1, "(or -1)." - print "Element #3 is %s." % terms[3] - -people = "Crosby Stills Nash Young".split() -what_about_that_list(people) -#----------------------------- -#=> The list now has 4 elements. -#=> The index of the last element is 3 (or -1). -#=> Element #3 is Young. -#----------------------------- -people.pop() -what_about_that_list(people) -#----------------------------- -people += [None] * (10000 - len(people)) -#----------------------------- -#>>> people += [None] * (10000 - len(people)) -#>>> what_about_that_list(people) -#The list now has 10000 elements. -#The index of the last element is 9999 (or -1). -#Element #3 is None. -#----------------------------- - -# @@PLEAC@@_4.4 -#----------------------------- -for item in mylist: - pass # do something with item -#----------------------------- -for user in bad_users: - complain(user) -#----------------------------- -import os -for (key, val) in sorted(os.environ.items()): - print "%s=%s" % (key, val) -#----------------------------- -for user in all_users: - disk_space = get_usage(user) # find out how much disk space in use - if disk_space > MAX_QUOTA: # if it's more than we want ... - complain(user) # ... then object vociferously -#----------------------------- -import os -for line in os.popen("who"): - if "dalke" in line: - print line, # or print line[:-1] - -# or: -print "".join([line for line in os.popen("who") - if "dalke" in line]), - -#----------------------------- -for line in myfile: - for word in line.split(): # Split on whitespace - print word[::-1], # reverse word - print - -# pre 2.3: -for line in myfile: - for word in line.split(): # Split on whitespace - chars = list(word) # Turn the string into a list of characters - chars.reverse() - print "".join(chars), - print -#----------------------------- -for item in mylist: - print "i =", item -#----------------------------- -# NOTE: you can't modify in place the way Perl does: -# data = [1, 2, 3] -# for elem in data: -# elem -= 1 -#print data -#=>[1, 2, 3] - -data = [1, 2, 3] -data = [i-1 for i in data] -print data -#=>[0, 1, 2] - -# or -for i, elem in enumerate(data): - data[i] = elem - 1 -#----------------------------- -# NOTE: strings are immutable in Python so this doesn't translate well. -s = s.strip() -data = [s.strip() for s in data] -for k, v in mydict.items(): - mydict[k] = v.strip() -#----------------------------- - -# @@PLEAC@@_4.5 -#----------------------------- -fruits = ["Apple", "Blackberry"] -for fruit in fruits: - print fruit, "tastes good in a pie." -#=> Apple tastes good in a pie. -#=> Blackberry tastes good in a pie. -#----------------------------- -# DON'T DO THIS: -for i in range(len(fruits)): - print fruits[i], "tastes good in a pie." - -# If you must explicitly index, use enumerate(): -for i, fruit in enumerate(fruits): - print "%s) %s tastes good in a pie."%(i+1, fruit) -#----------------------------- -rogue_cats = ["Morris", "Felix"] -namedict = { "felines": rogue_cats } -for cat in namedict["felines"]: - print cat, "purrs hypnotically." -print "--More--\nYou are controlled." -#----------------------------- -# As noted before, if you need an index, use enumerate() and not this: -for i in range(len(namedict["felines"])): - print namedict["felines"][i], "purrs hypnotically." -#----------------------------- - -# @@PLEAC@@_4.6 -#----------------------------- -uniq = list(set(mylist)) -#----------------------------- -# See http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/259174 -# for a more heavyweight version of a bag -seen = {} -for item in mylist: - seen[item] = seen.get(item, 0) + 1 - -uniq = seen.keys() -#----------------------------- -seen = {} -uniq = [] -for item in mylist: - count = seen.get(item, 0) - if count == 0: - uniq.append(item) - seen[item] = count + 1 -#----------------------------- -# generate a list of users logged in, removing duplicates -import os -usernames = [line.split()[0] for line in os.popen("who")] -uniq = sorted(set(usernames)) -print "users logged in:", " ".join(uniq) - -# DON'T DO THIS: -import os -ucnt = {} -for line in os.popen("who"): - username = line.split()[0] # Get the first word - ucnt[username] = ucnt.get(username, 0) + 1 # record the users' presence - -# extract and print unique keys -users = ucnt.keys() -users.sort() -print "users logged in:", " ".join(users) -#----------------------------- - -# @@PLEAC@@_4.7 -#----------------------------- -# assume a_list and b_list are already loaded -aonly = [item for item in a_list if item not in b_list] - -# A slightly more complex Pythonic version using sets - if you had a few -# lists, subtracting sets would be clearer than the listcomp version above -a_set = set(a_list) -b_set = set(b_list) -aonly = list(a_set - b_set) # Elements in a_set but not in b_set - -# DON'T DO THIS. -seen = {} # lookup table to test membership of B -aonly = [] # answer - -# build lookup table -for item in b_list: - seen[item] = 1 - -# find only elements in a_list and not in b_list -for item in a_list: - if not item not in seen: - # it's not in 'seen', so add to 'aonly' - aonly.append(item) -#----------------------------- -# DON'T DO THIS. There's lots of ways not to do it. -seen = {} # lookup table -aonly = [] # answer - -# build lookup table - unnecessary and poor Python style -[seen.update({x: 1}) for x in b_list] - -aonly = [item for item in a_list if item not in seen] - -#----------------------------- -aonly = list(set(a_list)) - -# DON'T DO THIS. -seen = {} -aonly = [] -for item in a_list: - if item not in seen: - aonly.append(item) - seen[item] = 1 # mark as seen -#----------------------------- -mydict["key1"] = 1 -mydict["key2"] = 2 -#----------------------------- -mydict[("key1", "key2")] = (1,2) -#----------------------------- -# DON'T DO THIS: -seen = dict.fromkeys(B.keys()) - -# DON'T DO THIS pre-2.3: -seen = {} -for term in B: - seen[term] = None -#----------------------------- -# DON'T DO THIS: -seen = {} -for k, v in B: - seen[k] = 1 -#----------------------------- - -# @@PLEAC@@_4.8 -#----------------------------- -a = (1, 3, 5, 6, 7, 8) -b = (2, 3, 5, 7, 9) - -a_set = set(a) -b_set = set(b) - -union = a_set | b_set # or a_set.union(b_set) -isect = a_set & b_set # or a_set.intersection(b_set) -diff = a_set ^ b_set # or a_set.symmetric_difference(b_set) - - -# DON'T DO THIS: -union_list = []; isect_list = []; diff = [] -union_dict = {}; isect_dict = {} -count = {} -#----------------------------- -# DON'T DO THIS: -for e in a: - union_dict[e] = 1 - -for e in b: - if union_dict.has_key(e): - isect_dict[e] = 1 - union_dict[e] = 1 - -union_list = union_dict.keys() -isect_list = isect_dict.keys() -#----------------------------- -# DON'T DO THIS: -for e in a + b: - if union.get(e, 0) == 0: - isect[e] = 1 - union[e] = 1 - -union = union.keys() -isect = isect.keys() -#----------------------------- -# DON'T DO THIS: -count = {} -for e in a + b: - count[e] = count.get(e, 0) + 1 - -union = []; isect = []; diff = [] - -for e in count.keys(): - union.append(e) - if count[e] == 2: - isect.append(e) - else: - diff.append(e) -#----------------------------- -# DON'T DO THIS: -isect = []; diff = []; union = [] -count = {} -for e in a + b: - count[e] = count.get(e, 0) + 1 - -for e, num in count.items(): - union.append(e) - [None, diff, isect][num].append(e) -#----------------------------- - -# @@PLEAC@@_4.9 -#----------------------------- -# "append" for a single term and -# "extend" for many terms -mylist1.extend(mylist2) -#----------------------------- -mylist1 = mylist1 + mylist2 -mylist1 += mylist2 -#----------------------------- -members = ["Time", "Flies"] -initiates = ["An", "Arrow"] -members.extend(initiates) -# members is now ["Time", "Flies", "An", "Arrow"] -#----------------------------- -members[2:] = ["Like"] + initiates -print " ".join(members) -members[:1] = ["Fruit"] # or members[1] = "Fruit" -members[-2:] = ["A", "Banana"] -print " ".join(members) -#----------------------------- -#=> Time Flies Like An Arrow -#=> Fruit Flies Like A Banana -#----------------------------- - -# @@PLEAC@@_4.10 -#----------------------------- -# reverse mylist into revlist - -revlist = mylist[::-1] - -# or -revlist = list(reversed(mylist)) - -# or pre-2.3 -revlist = mylist[:] # shallow copy -revlist.reverse() -#----------------------------- -for elem in reversed(mylist): - pass # do something with elem - -# or -for elem in mylist[::-1]: - pass # do something with elem - -# if you need the index and the list won't take too much memory: -for i, elem in reversed(list(enumerate(mylist))): - pass - -# If you absolutely must explicitly index: -for i in range(len(mylist)-1, -1, -1): - pass -#----------------------------- -descending = sorted(users, reverse=True) -#----------------------------- - -# @@PLEAC@@_4.11 -#----------------------------- -# remove n elements from the front of mylist -mylist[:n] = [] # or del mylist[:n] - -# remove n elements from front of mylist, saving them into front -front, mylist[:n] = mylist[:n], [] - -# remove 1 element from the front of mylist, saving it in front: -front = mylist.pop(0) - -# remove n elements from the end of mylist -mylist[-n:] = [] # or del mylist[-n:] - -# remove n elements from the end of mylist, saving them in end -end, mylist[-n:] = mylist[-n:], [] - -# remove 1 element from the end of mylist, saving it in end: -end = mylist.pop() - -#----------------------------- -def shift2(terms): - front = terms[:2] - terms[:2] = [] - return front - -def pop2(terms): - back = terms[-2:] - terms[-2:] = [] - return back -#----------------------------- -friends = "Peter Paul Mary Jim Tim".split() -this, that = shift2(friends) -# 'this' contains Peter, 'that' has Paul, and -# 'friends' has Mary, Jim, and Tim - -beverages = "Dew Jolt Cola Sprite Fresca".split() -pair = pop2(beverages) -# pair[0] contains Sprite, pair[1] has Fresca, -# and 'beverages' has (Dew, Jolt, Cola) - -# In general you probably shouldn't do things that way because it's -# not clear from these calls that the lists are modified. -#----------------------------- - -# @@PLEAC@@_4.12 -for item in mylist: - if criterion: - pass # do something with matched item - break -else: - pass # unfound -#----------------------------- -for idx, elem in enumerate(mylist): - if criterion: - pass # do something with elem found at mylist[idx] - break -else: - pass ## unfound -#----------------------------- -# Assuming employees are sorted high->low by wage. -for employee in employees: - if employee.category == 'engineer': - highest_engineer = employee - break - -print "Highest paid engineer is:", highest_engineer.name -#----------------------------- -# If you need the index, use enumerate: -for i, employee in enumerate(employees): - if employee.category == 'engineer': - highest_engineer = employee - break -print "Highest paid engineer is: #%s - %s" % (i, highest_engineer.name) - - -# The following is rarely appropriate: -for i in range(len(mylist)): - if criterion: - pass # do something - break -else: - pass ## not found -#----------------------------- - - -# @@PLEAC@@_4.13 -matching = [term for term in mylist if test(term)] -#----------------------------- -matching = [] -for term in mylist: - if test(term): - matching.append(term) -#----------------------------- -bigs = [num for num in nums if num > 1000000] -pigs = [user for (user, val) in users.items() if val > 1e7] -#----------------------------- -import os -matching = [line for line in os.popen("who") - if line.startswith("gnat ")] -#----------------------------- -engineers = [employee for employee in employees - if employee.position == "Engineer"] -#----------------------------- -secondary_assistance = [applicant for applicant in applicants - if 26000 <= applicant.income < 30000] -#----------------------------- - -# @@PLEAC@@_4.14 -sorted_list = sorted(unsorted_list) -#----------------------------- -# pids is an unsorted list of process IDs -import os, signal, time -for pid in sorted(pids): - print pid - -pid = raw_input("Select a process ID to kill: ") -try: - pid = int(pid) -except ValueError: - raise SystemExit("Exiting ... ") -os.kill(pid, signal.SIGTERM) -time.sleep(2) -try: - os.kill(pid, signal.SIGKILL) -except OSError, err: - if err.errno != 3: # was it already killed? - raise -#----------------------------- -descending = sorted(unsorted_list, reverse=True) -#----------------------------- -allnums = [4, 19, 8, 3] -allnums.sort(reverse=True) # inplace -#----------------------------- -# pre 2.3 -allnums.sort() # inplace -allnums.reverse() # inplace -#or -allnums = sorted(allnums, reverse=True) # reallocating -#----------------------------- - -# @@PLEAC@@_4.15 -ordered = sorted(unordered, cmp=compare) -#----------------------------- -ordered = sorted(unordered, key=compute) - -# ...which is somewhat equivalent to: -precomputed = [(compute(x), x) for x in unordered] -precomputed.sort(lambda a, b: cmp(a[0], b[0])) -ordered = [v for k,v in precomputed.items()] -#----------------------------- -# DON'T DO THIS. -def functional_sort(mylist, function): - mylist.sort(function) - return mylist - -ordered = [v for k,v in functional_sort([(compute(x), x) for x in unordered], - lambda a, b: cmp(a[0], b[0]))] -#----------------------------- -ordered = sorted(employees, key=lambda x: x.name) -#----------------------------- -for employee in sorted(employees, key=lambda x: x.name): - print "%s earns $%s" % (employee.name, employee.salary) -#----------------------------- -sorted_employees = sorted(employees, key=lambda x: x.name): -for employee in sorted_employees: - print "%s earns $%s" % (employee.name, employee.salary) - -# load bonus -for employee in sorted_employees: - if bonus(employee.ssn): - print employee.name, "got a bonus!" -#----------------------------- -sorted_employees = sorted(employees, key=lambda x: (x.name, x.age)): -#----------------------------- -# NOTE: Python should allow access to the pwd fields by name -# as well as by position. -import pwd -# fetch all users -users = pwd.getpwall() -for user in sorted(users, key=lambda x: x[0]): - print user[0] -#----------------------------- -sorted_list = sorted(names, key=lambda x: x[:1]) -#----------------------------- -sorted_list = sorted(strings, key=len) -#----------------------------- -# DON'T DO THIS. -temp = [(len(s), s) for s in strings] -temp.sort(lambda a, b: cmp(a[0], b[0])) -sorted_list = [x[1] for x in temp] -#----------------------------- -# DON'T DO THIS. -def functional_sort(mylist, function): - mylist.sort(function) - return mylist - -sorted_fields = [v for k,v in functional_sort( - [(int(re.search(r"(\d+)", x).group(1)), x) for x in fields], - lambda a, b: cmp(a[0], b[0]))] -#----------------------------- -entries = [line[:-1].split() for line in open("/etc/passwd")] - -for entry in sorted(entries, key=lambda x: (x[3], x[2], x[0])): - print entry -#----------------------------- - -# @@PLEAC@@_4.16 -#----------------------------- -import itertools -for process in itertools.cycle([1, 2, 3, 4, 5]): - print "Handling process", process - time.sleep(1) - -# pre 2.3: -import time -class Circular(object): - def __init__(self, data): - assert len(data) >= 1, "Cannot use an empty list" - self.data = data - - def __iter__(self): - while True: - for elem in self.data: - yield elem - -circular = Circular([1, 2, 3, 4, 5]) - -for process in circular: - print "Handling process", process - time.sleep(1) - -# DON'T DO THIS. All those pops and appends mean that the list needs to be -# constantly reallocated. This is rather bad if your list is large: -import time -class Circular(object): - def __init__(self, data): - assert len(data) >= 1, "Cannot use an empty list" - self.data = data - - def next(self): - head = self.data.pop(0) - self.data.append(head) - return head - -circular = Circular([1, 2, 3, 4, 5]) -while True: - process = circular.next() - print "Handling process", process - time.sleep(1) -#----------------------------- - -# @@PLEAC@@_4.17 -#----------------------------- -# generate a random permutation of mylist in place -import random -random.shuffle(mylist) -#----------------------------- - -# @@PLEAC@@_4.18 -#----------------------------- -import sys - -def make_columns(mylist, screen_width=78): - if mylist: - maxlen = max([len(elem) for elem in mylist]) - maxlen += 1 # to make extra space - - cols = max(1, screen_width/maxlen) - rows = 1 + len(mylist)/cols - - # pre-create mask for faster computation - mask = "%%-%ds " % (maxlen-1) - - for n in range(rows): - row = [mask%elem - for elem in mylist[n::rows]] - yield "".join(row).rstrip() - -for row in make_columns(sys.stdin.readlines(), screen_width=50): - print row - - -# A more literal translation -import sys - -# subroutine to check whether at last item on line -def EOL(item): - return (item+1) % cols == 0 - -# Might not be portable to non-linux systems -def getwinsize(): - # Use the curses module if installed - try: - import curses - stdscr = curses.initscr() - rows, cols = stdscr.getmaxyx() - return cols - except ImportError: - pass - - # Nope, so deal with ioctl directly. What value for TIOCGWINSZ? - try: - import termios - TIOCGWINSZ = termios.TIOCGWINSZ - except ImportError: - TIOCGWINSZ = 0x40087468 # This is Linux specific - - import struct, fcntl - s = struct.pack("HHHH", 0, 0, 0, 0) - try: - x = fcntl.ioctl(sys.stdout.fileno(), TIOCGWINSZ, s) - except IOError: - return 80 - rows, cols = struct.unpack("HHHH", x)[:2] - return cols - -cols = getwinsize() - -data = [s.rstrip() for s in sys.stdin.readlines()] -if not data: - maxlen = 1 -else: - maxlen = max(map(len, data)) - -maxlen += 1 # to make extra space - -# determine boundaries of screen -cols = (cols / maxlen) or 1 -rows = (len(data)+cols) / cols - -# pre-create mask for faster computation -mask = "%%-%ds " % (maxlen-1) - -# now process each item, picking out proper piece for this position -for item in range(rows * cols): - target = (item % cols) * rows + (item/cols) - if target < len(data): - piece = mask % data[target] - else: - piece = mask % "" - if EOL(item): - piece = piece.rstrip() # don't blank-pad to EOL - sys.stdout.write(piece) - if EOL(item): - sys.stdout.write("\n") - -if EOL(item): - sys.stdout.write("\n") -#----------------------------- - -# @@PLEAC@@_4.19 -#----------------------------- -def factorial(n): - s = 1 - while n: - s *= n - n -= 1 - return s -#----------------------------- -def permute(alist, blist=[]): - if not alist: - yield blist - for i, elem in enumerate(alist): - for elem in permute(alist[:i] + alist[i+1:], blist + [elem]): - yield elem - -for permutation in permute(range(4)): - print permutation -#----------------------------- -# DON'T DO THIS -import fileinput - -# Slightly modified from -# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66463 -def print_list(alist, blist=[]): - if not alist: - print ' '.join(blist) - for i in range(len(alist)): - blist.append(alist.pop(i)) - print_list(alist, blist) - alist.insert(i, blist.pop()) - -for line in fileinput.input(): - words = line.split() - print_list(words) -#----------------------------- -class FactorialMemo(list): - def __init__(self): - self.append(1) - - def __call__(self, n): - try: - return self[n] - except IndexError: - ret = n * self(n-1) - self.append(ret) - return ret - -factorial = FactorialMemo() - -import sys -import time -sys.setrecursionlimit(10000) - -start = time.time() -factorial(2000) -f1 = time.time() - start -factorial(2100) # First 2000 values are cached already -f2 = time.time() - f1 - start -print "Slow first time:", f1 -print "Quicker the second time:", f2 -#----------------------------- - -class MemoizedPermutations(list): - def __init__(self, alist): - self.permute(alist, []) - - def permute(self, alist, blist): - if not alist: - self.append(blist) - for i, elem in enumerate(alist): - self.permute(alist[:i] + alist[i+1:], blist + [elem]) - - def __call__(self, seq, idx): - return [seq[n] for n in self[idx]] - - -p5 = MemoizedPermutations(range(5)) - -words = "This sentence has five words".split() -print p5(words, 17) -print p5(words, 81) -#----------------------------- - -# @@PLEAC@@_5.0 -#----------------------------- -# dictionaries -age = {"Nat": 24, - "Jules": 24, - "Josh": 17} -#----------------------------- -age = {} -age["Nat"] = 24 -age["Jules"] = 25 -age["Josh"] = 17 -#----------------------------- -food_color = {"Apple": "red", - "Banana": "yellow", - "Lemon": "yellow", - "Carrot": "orange" - } -#----------------------------- -# NOTE: keys must be quoted in Python - - -# @@PLEAC@@_5.1 -mydict[key] = value -#----------------------------- -# food_color defined per the introduction -food_color["Raspberry"] = "pink" -print "Known foods:" -for food in food_color: - print food - -#=> Known foods: -#=> Raspberry -#=> Carrot -#=> Lemon -#=> Apple -#=> Banana -#----------------------------- - -# @@PLEAC@@_5.2 -# does mydict have a value for key? -if key in mydict: - pass # it exists -else: - pass # it doesn't - -#----------------------------- -# food_color per the introduction -for name in ("Banana", "Martini"): - if name in food_color: - print name, "is a food." - else: - print name, "is a drink." - -#=> Banana is a food. -#=> Martini is a drink. -#----------------------------- -age = {} -age["Toddler"] = 3 -age["Unborn"] = 0 -age["Phantasm"] = None - -for thing in ("Toddler", "Unborn", "Phantasm", "Relic"): - print ("%s:"%thing), - if thing in age: - print "Exists", - if age[thing] is not None: - print "Defined", - if age[thing]: - print "True", - print -#=> Toddler: Exists Defined True -#=> Unborn: Exists Defined -#=> Phantasm: Exists -#=> Relic: -#----------------------------- -# Get file sizes for the requested filenames -import fileinput, os -size = {} -for line in fileinput.input(): - filename = line.rstrip() - if filename in size: - continue - size[filename] = os.path.getsize(filename) - - -# @@PLEAC@@_5.3 -# remove key and its value from mydict -del mydict[key] -#----------------------------- -# food_color as per Introduction -def print_foods(): - foods = food_color.keys() - - print "Keys:", " ".join(foods) - print "Values:", - - for food in foods: - color = food_color[food] - if color is not None: - print color, - else: - print "(undef)", - print - -print "Initially:" -print_foods() - -print "\nWith Banana set to None" -food_color["Banana"] = None -print_foods() - -print "\nWith Banana deleted" -del food_color["Banana"] -print_foods() - -#=> Initially: -#=> Keys: Carrot Lemon Apple Banana -#=> Values: orange yellow red yellow -#=> -#=> With Banana set to None -#=> Keys: Carrot Lemon Apple Banana -#=> Values: orange yellow red (undef) -#=> -#=> With Banana deleted -#=> Keys: Carrot Lemon Apple -#=> Values: orange yellow red -#----------------------------- -for key in ["Banana", "Apple", "Cabbage"]: - del food_color[key] -#----------------------------- - - -# @@PLEAC@@_5.4 -#----------------------------- -for key, value in mydict.items(): - pass # do something with key and value - -# If mydict is large, use iteritems() instead -for key, value in mydict.iteritems(): - pass # do something with key and value - -#----------------------------- -# DON'T DO THIS: -for key in mydict.keys(): - value = mydict[key] - # do something with key and value -#----------------------------- -# food_color per the introduction -for food, color in food_color.items(): - print "%s is %s." % (food, color) - -# DON'T DO THIS: -for food in food_color: - color = food_color[food] - print "%s is %s." % (food, color) - -#----------------------------- -print """%(food)s - -is - -%(color)s. -""" % vars() -#----------------------------- -for food, color in sorted(food_color.items()): - print "%s is %s." % (food, color) - -#----------------------------- -#!/usr/bin/env python -# countfrom - count number of messages from each sender - -import sys -if len(sys.argv) > 1: - infile = open(sys.argv[1]) -else: - infile = sys.stdin - -counts = {} -for line in infile: - if line.startswith("From: "): - name = line[6:-1] - counts[name] = counts.get(name, 0) + 1 - -for (name, count) in sorted(counts.items()): - print "%s: %s" % (name, count) - -#----------------------------- - - -# @@PLEAC@@_5.5 -for key, val in mydict.items(): - print key, "=>", val -#----------------------------- -print "\n".join([("%s => %s" % item) for item in mydict.items()]) -#----------------------------- -print mydict -#=> {'firstname': 'Andrew', 'login': 'dalke', 'state': 'New Mexico', 'lastname': 'Dalke'} -#----------------------------- -import pprint -pprint.pprint(dict) -#=> {'firstname': 'Andrew', -#=> 'lastname': 'Dalke', -#=> 'login': 'dalke', -#=> 'state': 'New Mexico'} -#----------------------------- - - -# @@PLEAC@@_5.6 -#----------------------------- -class SequenceDict(dict): - """ - Dictionary that remembers the insertion order. - The lists returned by keys(), values() and items() are - in the insertion order. - """ - def __init__(self, *args): - self._keys={} # key --> id - self._ids={} # id --> key - self._next_id=0 - - def __setitem__(self, key, value): - self._keys[key]=self._next_id - self._ids[self._next_id]=key - self._next_id+=1 - return dict.__setitem__(self, key, value) - - def __delitem__(self, key): - id=self._keys[key] - del(self._keys[key]) - del(self._ids[id]) - return dict.__delitem__(self, key) - - def values(self): - values=[] - ids=list(self._ids.items()) - ids.sort() - for id, key in ids: - values.append(self[key]) - return values - - def items(self): - items=[] - ids=list(self._ids.items()) - ids.sort() - for id, key in ids: - items.append((key, self[key])) - return items - - def keys(self): - ids=list(self._ids.items()) - ids.sort() - keys=[] - for id, key in ids: - keys.append(key) - return keys - - def update(self, d): - for key, value in d.items(): - self[key]=value - - def clear(self): - dict.clear(self) - self._keys={} - self._ids={} - self._next_id=0 - -def testSequenceDict(): - sd=SequenceDict() - - # First Test - sd[3]="first" - sd[2]="second" - sd[1]="third" - print sd.keys() - print sd.items() - print sd.values() - - del(sd[1]) - del(sd[2]) - del(sd[3]) - - print sd.keys(), sd.items(), sd.values() - print sd._ids, sd._keys - - print "---------------" - # Second Test - sd["b"]="first" - sd["a"]="second" - sd.update({"c": "third"}) - print sd.keys() - print sd.items() - print sd.values() - - del(sd["b"]) - del(sd["a"]) - del(sd["c"]) - - print sd.keys(), sd.items(), sd.values() - print sd._ids, sd._keys - -def likePerlCookbook(): - food_color=SequenceDict() - food_color["Banana"]="Yellow"; - food_color["Apple"]="Green"; - food_color["Lemon"]="Yellow" - print "In insertion order, the foods' color are:" - for food, color in food_color.items(): - print "%s is colored %s" % (food, color) - -if __name__=="__main__": - #testSequenceDict() - likePerlCookbook() - - -# @@PLEAC@@_5.7 -import os -ttys = {} - -who = os.popen("who") - -for line in who: - user, tty = line.split()[:2] - ttys.setdefault(user, []).append(tty) - -for (user, tty_list) in sorted(ttys.items()): - print user + ": " + " ".join(tty_list) -#----------------------------- -import pwd -for (user, tty_list) in ttys.items(): - print user + ":", len(tty_list), "ttys." - for tty in sorted(tty_list): - try: - uid = os.stat("/dev/" + tty).st_uid - user = pwd.getpwuid(uid)[0] - except os.error: - user = "(not available)" - print "\t%s (owned by %s)" % (tty, user) - -# @@PLEAC@@_5.8 -# lookup_dict maps keys to values -reverse = dict([(val, key) for (key, val) in lookup_dict.items()]) -#----------------------------- -surname = {"Mickey": "Mantle", "Babe": "Ruth"} -first_name = dict([(last, first) for (first, last) in surname.items()]) - -print first_name["Mantle"] -#=> Mickey -#----------------------------- -#!/usr/bin/perl -w -# foodfind - find match for food or color - -import sys -if not sys.argv[1:]: - raise SystemExit("usage: foodfind food_or_color") -given = sys.argv[1] - -color_dict = {"Apple": "red", - "Banana": "yellow", - "Lemon": "yellow", - "Carrot": "orange", - } -food_dict = dict([(color, food) for (food, color) in color_dict.items()]) - -if given in color_dict: - print given, "is a food with color", color_dict[given] -elif given in food_dict: - print food_dict[given], "is a food with color", given -#----------------------------- -# food_color as per the introduction -foods_with_color = {} -for food, color in food_color.items(): - foods_with_color.setdefault(color, []).append(food) - -print " ".join(foods_with_color["yellow"]), "were yellow foods." -#----------------------------- - -# @@PLEAC@@_5.9 -#----------------------------- -# mydict is the hash to sort -for key, value in sorted(mydict.items()): - # do something with key, value -#----------------------------- -# food_color as per section 5.8 -for food, color in sorted(food_color.items()): - print "%s is %s." % (food, color) -#----------------------------- -# NOTE: alternative version -for item in sorted(food_color.items()): - print "%s is %s." % item -#----------------------------- -# NOTE: alternative version showing a user-defined function -def food_cmp(x, y): - return cmp(x, y) - -for food, color in sorted(food_color, cmp=food_cmp): - print "%s is %s." % (food, color) -#----------------------------- -def food_len_cmp(x, y): - return cmp(len(x), len(y)) - -for food in sorted(food_color, cmp=food_len_cmp): - print "%s is %s." % (food, food_color[food]) - -# In this instance, however, the following is both simpler and faster: -for food in sorted(food_color, key=len): - print "%s is %s." % (food, food_color[food]) -#----------------------------- - - -# @@PLEAC@@_5.10 -#----------------------------- -merged = {} -merged.update(a_dict) -merged.update(b_dict) - -#----------------------------- -# NOTE: alternative version -merged = a_dict.copy() -merged.update(b_dict) -#----------------------------- -# DON'T DO THIS: - -merged = {} -for k, v in a_dict.items(): - merged[k] = v -for k, v in b_dict.items(): - merged[k] = v -#----------------------------- -# food_color as per section 5.8 -drink_color = {"Galliano": "yellow", - "Mai Tai": "blue"} - -ingested_color = drink_color.copy() -ingested_color.update(food_color) -#----------------------------- -# DON'T DO THIS: -drink_color = {"Galliano": "yellow", - "Mai Tai": "blue"} - -substance_color = {} -for k, v in food_color.items(): - substance_color[k] = v -for k, v in drink_color.items(): - substance_color[k] = v -#----------------------------- -# DON'T DO THIS: -substance_color = {} -for mydict in (food_color, drink_color): - for k, v in mydict: - substance_color[k] = v -#----------------------------- -# DON'T DO THIS: -substance_color = {} -for item in food_color.items() + drink_color.items(): - for k, v in mydict: - substance_color[k] = v -#----------------------------- -substance_color = {} -for mydict in (food_color, drink_color): - for k, v in mydict.items(): - if substance_color.has_key(k): - print "Warning:", k, "seen twice. Using the first definition." - continue - substance_color[k] = v - -# I think it's a copy, in which case -all_colors = new_colors.copy() - - -# @@PLEAC@@_5.11 -common = [k for k in dict1 if k in dict2] -#----------------------------- -this_not_that = [k for k in dict1 if k not in dict2] -#----------------------------- -# citrus_color is a dict mapping citrus food name to its color. -citrus_color = {"Lemon": "yellow", - "Orange": "orange", - "Lime": "green"} - -# build up a list of non-citrus foods -non_citrus = [k for k in food_color if k not in citruscolor] -#----------------------------- - -# @@PLEAC@@_5.12 -#----------------------------- -# references as keys of dictionaries is no pb in python - -name = {} -for filename in ("/etc/termcap", "/vmunix", "/bin/cat"): - try: - myfile = open(filename) - except IOError: - pass - else: - names[myfile] = filename - -print "open files:", ", ".join(name.values()) -for f, fname in name.items(): - f.seek(0, 2) # seek to the end - print "%s is %d bytes long." % (fname, f.tell()) -#----------------------------- - -# @@PLEAC@@_5.13 -# Python doesn't allow presizing of dicts, but hashing is efficient - -# it only re-sizes at intervals, not every time an item is added. - -# @@PLEAC@@_5.14 -count = {} -for element in mylist: - count[element] = count.get(element, 0) + 1 - -# @@PLEAC@@_5.15 -#----------------------------- -import fileinput - -father = {'Cain': 'Adam', - 'Abel': 'Adam', - 'Seth': 'Adam', - 'Enoch': 'Cain', - 'Irad': 'Enoch', - 'Mehujael': 'Irad', - 'Methusael': 'Mehujael', - 'Lamech': 'Methusael', - 'Jabal': 'Lamech', - 'Tubalcain': 'Lamech', - 'Enos': 'Seth', - } - -for line in fileinput.input(): - person = line.rstrip() - while person: # as long as we have people, - print person, # print the current name - person = father.get(person) # set the person to the person's father - print - -#----------------------------- -import fileinput - -children = {} -for k, v in father.items(): - children.setdefault(v, []).append(k) - -for line in fileinput.input(): - person = line.rstrip() - kids = children.get(person, ["nobody"]) - print person, "begat", ", ".join(kids) - -#----------------------------- -import sys, re -pattern = re.compile(r'^\s*#\s*include\s*<([^>]+)') -includes = {} -for filename in filenames: - try: - infile = open(filename) - except IOError, err: - print>>sys.stderr, err - continue - for line in infile: - match = pattern.match(line) - if match: - includes.setdefault(match.group(1), []).append(filename) -#----------------------------- -# list of files that don't include others -mydict = {} -for e in reduce(lambda a,b: a + b, includes.values()): - if not includes.has_key(e): - mydict[e] = 1 -include_free = mydict.keys() -include_free.sort() - -# @@PLEAC@@_5.16 -#----------------------------- -#!/usr/bin/env python -w -# dutree - print sorted indented rendition of du output -import os, sys - -def get_input(args): - # NOTE: This is insecure - use only from trusted code! - cmd = "du " + " ".join(args) - infile = os.popen(cmd) - - dirsize = {} - kids = {} - for line in infile: - size, name = line[:-1].split("\t", 1) - dirsize[name] = int(size) - parent = os.path.dirname(name) - kids.setdefault(parent, []).append(name) - # Remove the last field added, which is the root - kids[parent].pop() - if not kids[parent]: - del kids[parent] - - return name, dirsize, kids - -def getdots(root, dirsize, kids): - size = cursize = dirsize[root] - if kids.has_key(root): - for kid in kids[root]: - cursize -= dirsize[kid] - getdots(kid, dirsize, kids) - if size != cursize: - dot = root + "/." - dirsize[dot] = cursize - kids[root].append(dot) - -def output(root, dirsize, kids, prefix = "", width = 0): - path = os.path.basename(root) - size = dirsize[root] - fmt = "%" + str(width) + "d %s" - line = fmt % (size, path) - print prefix + line - - prefix += (" " * (width-1)) + "| " + (" " * len(path)) - - if kids.has_key(root): - kid_list = kids[root] - kid_list.sort(lambda x, y, dirsize=dirsize: - cmp(dirsize[x], dirsize[y])) - width = len(str(dirsize[kid_list[-1]])) - for kid in kid_list: - output(kid, dirsize, kids, prefix, width) - -def main(): - root, dirsize, kids = get_input(sys.argv[1:]) - getdots(root, dirsize, kids) - output(root, dirsize, kids) - -if __name__ == "__main__": - main() - - -# @@PLEAC@@_6.0 -# Note: regexes are used less often in Python than in Perl as tasks are often -# covered by string methods, or specialised objects, modules, or packages. - -import re # "re" is the regular expression module. -re.search("sheep",meadow) # returns a MatchObject is meadow contains "sheep". -if not re.search("sheep",meadow): - print "no sheep on this meadow only a fat python." -# replacing strings is not done by "re"gular expressions. -meadow = meadow.replace("old","new") # replace "old" with "new" and assign result. -#----------------------------- -re.search("ovine",meadow) - -meadow = """Fine bovines demand fine toreadors. -Muskoxen are polar ovibovine species. -Grooviness went out of fashion decades ago.""" - -meadow = "Ovines are found typically in ovaries." - -if re.search(r"\bovines\b",meadow,re.I) : print "Here be sheep!" -#----------------------------- -# The tricky bit -mystr = "good food" -re.sub("o*","e",mystr,1) # gives 'egood food' - -echo ababacaca | python -c "import sys,re; print re.search('(a|ba|b)+(a|ac)+',sys.stdin.read()).group()" -#----------------------------- -# pattern matching modifiers -# assume perl code iterates over some file -import re, fileinput -for ln = fileinput.input(): - fnd = re.findall("(\d+)",ln) - if len(fnd) > 0: - print "Found number %s" % (fnd[0]) -# ---------------------------- -digits = "123456789" -nonlap = re.findall("(\d\d\d)", digits) -yeslap = ["not yet"] -print "Non-overlapping:",",".join(nonlap) -print "Overlapping :",",".join(yeslap) -# ---------------------------- -mystr = "And little lambs eat ivy" -fnd = re.search("(l[^s]*s)", mystr) -print "(%s) (%s) (%s)" % (mystr[:fnd.start()], fnd.group(), mystr[fnd.end():]) -# (And ) (little lambs) ( eat ivy) - - -# @@PLEAC@@_6.1 -import re -dst = re.sub("this","that",src) -#----------------------------- -# strip to basename -basename = re.sub(".*/(?=[^/]+)","",progname) - -# Make All Words Title-Cased -# DON'T DO THIS - use str.title() instead -def cap(mo): return mo.group().capitalize() -re.sub("(?P<n>\w+)",cap,"make all words title-cased") - -# /usr/man/man3/foo.1 changes to /usr/man/cat3/foo.1 -manpage = "/usr/man/man3/foo.1" -catpage = re.sub("man(?=\d)","cat",manpage) -#----------------------------- -bindirs = "/usr/bin /bin /usr/local/bin".split() -libdirs = [d.replace("bin", "lib") for d in bindirs] - -print " ".join(libdirs) -#=> /usr/lib /lib /usr/local/lib -#----------------------------- -# strings are never modified in place. -#----------------------------- - -# @@PLEAC@@_6.2 -##--------------------------- - -# DON'T DO THIS. use line[:-1].isalpha() [this probably goes for the -# remainder of this section too!] -import re -if re.match("^[A-Za-z]+$",line): - print "pure alphabetic" -##--------------------------- -if re.match(r"^[^\W\d_]+$", line, re.LOCALE): - print "pure alphabetic" -##--------------------------- -import re -import locale - -try: - locale.setlocale(locale.LC_ALL, 'fr_CA.ISO8859-1') -except: - print "couldn't set locale to French Cnadian" - raise SystemExit - -DATA=""" -silly -façade -coöperate -niño -Renée -Molière -hæmoglobin -naïve -tschüß -random!stuff#here -""" - -for ln in DATA.split(): - ln = ln.rstrip() - if re.match(r"^[^\W\d_]+$",ln,re.LOCALE): - print "%s: alphabetic" % (ln) - else: - print "%s: line noise" % (ln) -# although i dont think "coöperate" should be in canadian -##--------------------------- - -# @@PLEAC@@_6.3 -# Matching Words -"\S+" # as many non-whitespace bytes as possible -"[A-Za-z'-]+" # as many letters, apostrophes, and hyphens - -# string split is similar to splitting on "\s+" -"A text with some\tseparator".split() - -"\b*([A-Za-z]+)\b*" # word boundaries -"\s*([A-Za-z]+)\s*" # might work too as on letters are allowed. - -re.search("\Bis\B","this thistle") # matches on thistle not on this -re.search("\Bis\B","vis-a-vis") # does not match - -# @@PLEAC@@_6.4 -#----------------------------- -#!/usr/bin/python -# resname - change all "foo.bar.com" style names in the input stream -# into "foo.bar.com [204.148.40.9]" (or whatever) instead - -import socket # load inet_addr -import fileinput -import re - -match = re.compile("""(?P<hostname> # capture hostname - (?: # these parens for grouping only - [\w-]+ # hostname component - \. # ant the domain dot - ) + # now repeat that whole thing a bunch of times - [A-Za-z] # next must be a letter - [\w-] + # now trailing domain part - ) # end of hostname capture - """,re.VERBOSE) # for nice formatting - -def repl(match_obj): - orig_hostname = match_obj.group("hostname") - try: - addr = socket.gethostbyname(orig_hostname) - except socket.gaierror: - addr = "???" - return "%s [%s]" % (orig_hostname, addr) - -for ln in fileinput.input(): - print match.sub(repl, ln) -#----------------------------- -re.sub("""(?x) # nicer formatting - \# # a pound sign - (\w+) # the variable name - \# # another pound sign - """, - lambda m: eval(m.group(1)), # replace with the value of the global variable - line - ) -##----------------------------- -re.sub("""(?x) # nicer formatting - \# # a pound sign - (\w+) # the variable name - \# # another pound sign - """, - lambda m: eval(eval(m.group(1))), # replace with the value of *any* variable - line - ) -##----------------------------- - -# @@PLEAC@@_6.5 -import re -pond = "one fish two fish red fish blue fish" -fishes = re.findall(r"(?i)(\w+)\s+fish\b",pond) -if len(fishes)>2: - print "The third fish is a %s one." % (fishes[2]) -##----------------------------- -re.findall(r"(?i)(?:\w+\s+fish\s+){2}(\w+)\s+fish",pond) -##----------------------------- -count = 0 -for match_object in re.finditer(r"PAT", mystr): - count += 1 # or whatever you want to do here - -# "progressive" matching might be better if one wants match 5 from 50. -# to count use -count = len(re.findall(r"PAT",mystr)) -count = len(re.findall(r"aba","abaababa")) - -# "count" overlapping matches -count = len(re.findall(r"(?=aba)","abaababa")) - -# FASTEST non-overlapping might be str.count -"abaababa".count("aba") -##----------------------------- -pond = "one fish two fish red fish blue fish" -colors = re.findall(r"(?i)(\w+)\s+fish\b",pond) # get all matches -color = colors[2] # then the one we want - -# or without a temporary list -color = re.findall(r"(?i)(\w+)\s+fish\b",pond)[2] # just grab element 3 - -print "The third fish in the pond is %s." % (color) -##----------------------------- -import re - -pond = "one fish two fish red fish blue fish" -matches = re.findall(r"(\w+)\s+fish\b",pond) -evens = [fish for (i, fish) in enumerate(matches) if i%2] -print "Even numbered fish are %s." % (" ".join(evens)) -##----------------------------- -count = 0 -def four_is_sushi(match_obj): - global count - count += 1 - if count==4: - return "sushi%s" % (match_obj.group(2)) - return "".join(match_obj.groups()) - -re.sub(r"""(?x) # VERBOSE - \b # makes next \w more efficient - ( \w+ ) # this is what we'll be changing - ( - \s+ fish \b - )""", - four_is_sushi, - pond) -# one fish two fish red fish sushi fish -##----------------------------- -# greedily -last_fish = re.findall(r"(?i).*\b(\w+)\s+fish\b",pond) -##----------------------------- -pond = "One fish two fish red fish blue fish swim here" -color = re.findall(r"(?i)\b(\w+)\s+fish\b",pond)[-1] -print "Last fish is "+color+"." -# FASTER using string. -lastfish = pond.rfind("fish") -color = pond[:lastfish].split()[-1] -##----------------------------- -r"""(?x) - A # find some pattern A - (?! # mustn't be able to find - .* # something - A # and A - ) - $ # through the end of string - """ - -pond = "One fish two fish red fish blue fish swim here" -fnd = re.findall(r"""(?xis) # VERBOSE, CASEINSENSITIVE, DOTALL - \b ( \w+ ) \s+ fish \b - (?! .* \b fish \b )""", - pond) -if len(fnd): - print "Last fish is %s." % (fnd[0]) -else: - print "Failed!" - - -# @@PLEAC@@_6.6 -# Matching Multiple Lines -# -#!/usr/bin/python -# killtags - very bad html tag killer -import re -import sys - -text = open(sys.argv[1]).read() # read the whole file -text = re.sub("(?ms)<.*?>","",text) # strip tags (terrible -print text -## ---------------------------- -#!/usr/bin/python -# headerfy: change certain chapter headers to html -import sys, re - -match = re.compile(r"""(?xms) # re.VERBOSE, re.MULTILINE, and re.DOTALL - \A # start of the string - (?P<chapter> # capture in g<chapter> - Chapter # literal string - \s+ # mandatory whitespace - \d+ # decimal number - \s* # optional whitespace - : # a real colon - . * # anything not a newline till end of line - ) - """) -text = open(sys.argv[1]).read() # read the whole file -for paragraph in text.split("\n"): # split on unix end of lines - p = match.sub("<h1>\g<chapter></h1>",paragraph) - print p -## ---------------------------- -# the one liner does not run. -# python -c 'import sys,re; for p in open(sys.argv[1]).read().split("\n\n"): print re.sub(r"(?ms)\A(Chapter\s+\d+\s*:.*)","<h1>\g0</h1>",p)' -## ---------------------------- -match = re.compile(r"(?ms)^START(.*?)^END") - # s makes . span line boundaries - # m makes ^ match at the beginning of the string and at the beginning of each line - -chunk = 0 -for paragraph in open(sys.argv[1]).read().split("\n\n"): - chunk += 1 - fnd = match.findall(paragraph) - if fnd: - print "chunk %d in %s has <<%s>>" % (chunk,sys.argv[1],">>,<<".join(fnd)) -## ---------------------------- - -# @@PLEAC@@_6.7 -import sys -# Read the whole file and split -chunks = open(sys.argv[1]).read().split() # on whitespace -chunks = open(sys.argv[1]).read().split("\n") # on line ends - -# splitting on pattern -import re -pattern = r"x" -chunks = re.split(pattern, open(sys.argv[1]).read()) -##----------------------------- -chunks = re.split(r"(?m)^\.(Ch|Se|Ss)$",open(sys.argv[1]).read()) -print "I read %d chunks." % (len(chunks)) -# without delimiters -chunks = re.split(r"(?m)^\.(?:Ch|Se|Ss)$",open(sys.argv[1]).read()) - -# with delimiters -chunks = re.split(r"(?m)^(\.(?:Ch|Se|Ss))$",open(sys.argv[1]).read()) - -# with delimiters at chunkstart -chunks = re.findall(r"""(?xms) # multiline, dot matches lineend, allow comments - ((?:^\.)? # consume the separator if present - .*?) # match everything but not greedy - (?= # end the match on this but dont consume it - (?: # dont put into group [1] - ^\.(?:Ch|Se|Ss)$ # either end on one of the roff commands - |\Z # or end of text - ) - )""", - open(sys.argv[1]).read()) -# [1] if "?:" is removed the result holds tuples: ('.Ch\nchapter x','.Ch') -# which might be more usefull. - -# @@PLEAC@@_6.8 -##----------------------------- -# Python doesn't have perl's range operators -# If you want to only use a selected line range, use enumerate -# (though note that indexing starts at zero: -for i, line in enumerate(myfile): - if firstlinenum <= i < lastlinenum: - dosomethingwith(line) - -# Using patterned ranges is slightly trickier - -# You need to search for the first pattern then -# search for the next pattern: -import re -for line in myfile: - if re.match(pat1, line): - break - -dosomethingwith(line) # Only if pat1 can be on same line as pat2 - -for line in myfile: - if re.match(pat2, line): - break - dosomethingwith(line) -##----------------------------- -# If you need to extract ranges a lot, the following generator funcs -# may be useful: -def extract_range(myfile, start, finish): - for i, line in enumerate(myfile): - if start <= i < finish: - yield line - elif i == finish: - break - -for line in extract_range(open("/etc/passwd"), 3, 5): - print line - -def patterned_range(myfile, startpat, endpat=None): - startpat = re.compile(startpat) - if endpat is not None: - endpat = re.compile(endpat) - in_range = False - for line in myfile: - if re.match(startpat, line): - in_range = True - if in_range: - yield line - if endpat is not None and re.match(endpat, line): - break - -# DO NOT DO THIS. Use the email module instead -for line in patterned_range(msg, "^From:?", "^$"): - pass #... - - -# @@PLEAC@@_6.9 -tests = (("list.?",r"^list\..$"), - ("project.*",r"^project\..*$"), - ("*old",r"^.*old$"), - ("type*.[ch]",r"^type.*\.[ch]$"), - ("*.*",r"^.*\..*$"), - ("*",r"^.*$"), - ) - -# The book says convert "*","?","[","]" all other characters will be quoted. -# The book uses "\Q" which escapes any characters that would otherwise be -# treated as regular expression. -# Escaping every char fails as "\s" is not "s" in a regex. - -def glob2pat(globstr): - pat = globstr.replace("\\",r"\\") - pat = pat.replace(".",r"\.").replace("?",r".").replace("*",r".*") - - return "^"+pat+"$" - -for globstr, patstr in tests: - g2p = glob2pat(globstr) - if g2p != patstr: - print globstr, "failed! Should be", patstr, "but was", g2p - - -# @@PLEAC@@_6.10 - -# download the following standalone program -#!/usr/bin/python -# popgrep1 - grep for abbreviations of places that say "pop" -# version 1: slow but obvious way -import fileinput -import re -popstates = ["CO","ON","MI","WI","MN"] -for line in fileinput.input(): - for state in popstates: - if re.search(r"\b"+state+r"\b",line): - print line - - - -#----------------------------- -# download the following standalone program -#!/usr/bin/python -# popgrep2 - grep for abbreviations of places that say "pop" -# version 2: compile the patterns -import fileinput -import re -popstates = ["CO","ON","MI","WI","MN"] -state_re = [] -for state in popstates: - state_re.append(re.compile(r"\b"+state+r"\b")) -for line in fileinput.input(): - for state in state_re: - if state.search(line): - print line - - -#----------------------------- -# download the following standalone program -#!/usr/bin/python -# popgrep3 - grep for abbreviations of places that say "pop" -# version 3: compile a single pattern -import fileinput -import re -popstates = ["CO","ON","MI","WI","MN"] -state_re = re.compile(r"\b(?:"+"|".join(popstates)+r")\b") -for line in fileinput.input(): - if state_re.search(line): - print line - - -#----------------------------- -# download the following standalone program -#!/usr/bin/python -# grepauth - print lines that mention both Tom and Nat -import fileinput -import re - -def build_match_any(words): - return re.compile("|".join(words)) -def uniq(arr): - seen = {} - for item in arr: - seen[item] = seen.get(item, 0) + 1 - return seen.keys() -def build_match_all(words): - r = re.compile("|".join(words)) - c = lambda line: len(uniq(r.findall(line)))>=len(words) - return c - -any = build_match_any(("Tom","Nat")) -all = build_match_all(("Tom","Nat")) -for line in fileinput.input(): - if any.search(line): - print "any:", line - if all(line): - print "all:", line - - - -#----------------------------- - - -# @@PLEAC@@_6.11 -# Testing for a Valid Pattern - -import re -while True: - pat = raw_input("Pattern? ") - try: - re.compile(pat) - except re.error, err: - print "INVALID PATTERN", err - continue - break - -# ---- -def is_valid_pattern(pat): - try: - re.compile(pat) - except re.error: - return False - return True - -# ---- - -# download the following standalone program -#!/usr/bin/python -# paragrep - trivial paragraph grepper -# -# differs from perl version in parano. -# python version displays paragraph in current file. - -import sys, os.path, re -if len(sys.argv)<=1: - print "usage: %s pat [files]\n" % sys.argv[0] - sys.exit(1) - -pat = sys.argv[1] -try: - pat_re = re.compile(pat) -except: - print "%s: bad pattern %s: %s" % (sys.argv[1], pat, sys.exc_info()[1]) - sys.exit(1) -for filename in filter(os.path.isfile,sys.argv[2:]): - parano = 0 - for para in open(filename).read().split("\n\n"): - parano += 1 - if pat_re.search(para): - print filename, parano, para, "\n" - - - -# ---- - -# as we dont evaluate patterns the attack :: -# -# $pat = "You lose @{[ system('rm -rf *']} big here"; -# -# does not work. - - -# @@PLEAC@@_6.12 - -# download the following standalone program -#!/usr/bin/python -# localeg - demonstrates locale effects -# -# re must be told to respect locale either in the regexp -# "(?L)" or as flag to the call (python 2.4) "re.LOCALE". - -import sys -import re, string -from locale import LC_CTYPE, setlocale, getlocale - -name = "andreas k\xF6nig" -locale = {"German" : "de_DE.ISO_8859-1", "English" : "en_US"} -# us-ascii is not supported on linux py23 -# none works in activestate py24 - -try: - setlocale(LC_CTYPE, locale["English"]) -except: - print "Invalid locale %s" % locale["English"] - sys.exit(1) -english_names = [] -for n in re.findall(r"(?L)\b(\w+)\b",name): - english_names.append(n.capitalize()) - -try: - setlocale(LC_CTYPE, locale["German"]) -except: - print "Invalid locale %s" % locale["German"] - sys.exit(1) -german_names = map(string.capitalize, re.findall(r"(?L)\b(\w+)\b",name)) - -print "English names: %s" % " ".join(english_names) -print "German names: %s" % " ".join(german_names) - - -# @@PLEAC@@_6.13 -##----------------------------- -import difflib -matchlist = ["ape", "apple", "lapel", "peach", "puppy"] -print difflib.get_close_matches("appel", matchlist) -#=> ['lapel', 'apple', 'ape'] -##----------------------------- -# Also see: -# http://www.personal.psu.edu/staff/i/u/iua1/python/apse/ -# http://www.bio.cam.ac.uk/~mw263/pyagrep.html - -# @@PLEAC@@_6.14 -##----------------------------- -# To search (potentially) repeatedly for a pattern, use re.finditer(): - -# DO NOT DO THIS. Split on commas and convert elems using int() -mystr = "3,4,5,9,120" -for match in re.finditer("(\d+)", mystr): - n = match.group(0) - if n == "9": - break # '120' will never be matched - print "Found number", n - -# matches know their end position -mystr = "The year 1752 lost 10 days on the 3rd of September" -x = re.finditer("(\d+)", mystr) -for match in x: - n = match.group(0) - print "Found number", n - -tail = re.match("(\S+)", mystr[match.end():]) -if tail: - print "Found %s after the last number."%tail.group(0) - - -# @@PLEAC@@_6.15 -# Python's regexes are based on Perl's, so it has the non-greedy -# '*?', '+?', and '??' versions of '*', '+', and '?'. -# DO NOT DO THIS. import htmllib, formatter, etc, instead -#----------------------------- -# greedy pattern -txt = re.sub("<.*>", "", txt) # try to remove tags, very badly - -# non-greedy pattern -txt = re.sub("<.*?>", "", txt) # try to remove tags, still rather badly -#----------------------------- -txt = "<b><i>this</i> and <i>that</i> are important</b> Oh, <b><i>me too!</i></b>" - -print re.findall("<b><i>(.*?)</i></b>", txt -##----------------------------- -print re.findall("/BEGIN((?:(?!BEGIN).)*)END/", txt) -##----------------------------- -print re.findall("<b><i>((?:(?!<b>|<i>).)*)</i></b>", txt) -##----------------------------- -print re.findall("<b><i>((?:(?!<[ib]>).)*)</i></b>", txt) -##----------------------------- -print re.findall(""" - <b><i> - [^<]* # stuff not possibly bad, and not possibly the end. - (?: # at this point, we can have '<' if not part of something bad - (?! </?[ib]> ) # what we can't have - < # okay, so match the '<' - [^<]* # and continue with more safe stuff - ) * - </i></b> - """, re.VERBOSE, txt) -##----------------------------- - -# @@PLEAC@@_6.16 -##----------------------------- -text = """ -This is a test -test of the duplicate word finder. -""" -words = text.split() -for curr, next in zip(words[:-1], words[1:]): - if curr.upper() == next.upper(): - print "Duplicate word '%s' found." % curr - -# DON'T DO THIS -import re -pat = r""" - \b # start at a word boundary (begin letters) - (\S+) # find chunk of non-whitespace - \b # until another word boundary (end letters) - ( - \s+ # separated by some whitespace - \1 # and that very same chunk again - \b # until another word boundary - ) + # one or more sets of those - """ -for match in re.finditer(pat, text, flags=re.VERBOSE|re.IGNORECASE): - print "Duplicate word '%s' found." % match.group(1) -##----------------------------- -a = 'nobody'; -b = 'bodysnatcher'; - -text = a+" "+b -pat = r"^(\w+)(\w+) \2(\w+)$" -for match in re.finditer(pat, text): - m1, m2, m3 = match.groups() - print m2, "overlaps in %s-%s-%s"%(m1, m2, m3) -##----------------------------- -pat = r"^(\w+?)(\w+) \2(\w+)$" -##----------------------------- -try: - while True: - factor = re.match(r"^(oo+?)\1+$", n).group(1) - n = re.sub(factor, "o", n) - print len(factor) -except AttributeError: - print len(n) -##----------------------------- -def diaphantine(n, x, y, z): - pat = r"^(o*)\1{%s}(o*)\2{%s}(o*)\3{%s}$"%(x-1, y-1, z-1) - text = "o"*n - try: - vals = [len(v) for v in re.match(pat, text).groups()] - except ValueError: - print "No solutions." - else: - print "One solution is: x=%s, y=%s, z=%s."%tuple(vals) - -diaphantine(n=281, x=12, y=15, z=16) - -# @@PLEAC@@_6.17 -##----------------------------- -# Pass any of the following patterns to re.match(), etc -pat = "ALPHA|BETA" -pat = "^(?=.*ALPHA)(?=.*BETA)" -pat = "ALPHA.*BETA|BETA.*ALPHA" -pat = "^(?:(?!PAT).)*$" -pat = "(?=^(?:(?!BAD).)*$)GOOD" -##----------------------------- -if not re.match(pattern, text): - something() -##----------------------------- -if re.match(pat1, text) and re.match(pat2, text): - something() -##----------------------------- -if re.match(pat1, text) or re.match(pat2, text): - something() -##----------------------------- -# DON'T DO THIS. -"""minigrep - trivial grep""" -import sys, re - -pat = sys.argv[1] -for line in sys.stdin: - if re.match(pat, line): - print line[:-1] -##----------------------------- -if re.match(r"^(?=.*bell)(?=.*lab)", "labelled"): - something() -##----------------------------- -if re.search("bell", s) and re.search("lab", s): - something() -##----------------------------- -if re.match(""" - ^ # start of string - (?= # zero-width lookahead - .* # any amount of intervening stuff - bell # the desired bell string - ) # rewind, since we were only looking - (?= # and do the same thing - .* # any amount of intervening stuff - lab # and the lab part - ) - """, - murray_hill, - re.DOTALL | re.VERBOSE): - print "Looks like Bell Labs might be in Murray Hill!" -##----------------------------- -if re.match(r"(?:^.*bell.*lab)|(?:^.*lab.*bell)", "labelled"): - something() -##----------------------------- -brand = "labelled" -if re.match(""" - (?: # non-capturing grouper - ^ .*? # any amount of stuff at the front - bell # look for a bell - .*? # followed by any amount of anything - lab # look for a lab - ) # end grouper - | # otherwise, try the other direction - (?: # non-capturing grouper - ^ .*? # any amount of stuff at the front - lab # look for a lab - .*? # followed by any amount of anything - bell # followed by a bell - ) # end grouper - """, - brand, - re.DOTALL | re.VERBOSE): - print "Our brand has bell and lab separate." -##----------------------------- -x = "odlaw" -if re.match("^(?:(?!waldo).)*$", x): - print "There's no waldo here!" -##----------------------------- -if re.match(""" - ^ # start of string - (?: # non-capturing grouper - (?! # look ahead negation - waldo # is he ahead of us now? - ) # is so, the negation failed - . # any character (cuzza /s) - ) * # repeat that grouping 0 or more - $ # through the end of the string - """, - x, - re.VERBOSE | re.DOTALL): - print "There's no waldo here!\n"; -##----------------------------- - -# @@PLEAC@@_6.18 -# @@INCOMPLETE@@ -# @@INCOMPLETE@@ - -# @@PLEAC@@_6.19 -##----------------------------- -from email._parseaddr import AddressList - -print AddressList("fred&barney@stonehenge.com").addresslist[0] - -print AddressList("fred&barney@stonehenge.com (Hanna Barbara)").addresslist[0] - -name, address = AddressList("Mr Fooby Blah <me@nowhere.com>").addresslist[0] -print "%s's address is '%s'"%(name, address) - -# @@PLEAC@@_6.20 -##----------------------------- -# Assuming the strings all start with different letters, or you don't -# mind there being precedence, use the startswith string method: - -def get_action(answer): - answer = answer.lower() - actions = ["send", "stop", "abort", "list", "end"] - for action in actions: - if action.startswith(answer): - return action - -print "Action is %s."%get_action("L") -#=> Action is list. -##----------------------------- -#DON'T DO THIS: -import re -answer = "ab" -answer = re.escape(answer.strip()) -for action in ("SEND", "STOP", "ABORT", "LIST", "EDIT"): - if re.match(answer, action, flags=re.IGNORECASE): - print "Action is %s."%action.lower() -##----------------------------- -import re, sys -def handle_cmd(cmd): - cmd = re.escape(cmd.strip()) - for name, action in {"edit": invoke_editor, - "send": deliver_message, - "list": lambda: system(pager, myfile), - "abort": sys.exit, - } - if re.match(cmd, name, flags=re.IGNORECASE): - action() - break - else: - print "Unknown command:", cmd -handle_cmd("ab") - -# @@PLEAC@@_6.21 -##----------------------------- -# urlify - wrap HTML links around URL-like constructs -import re, sys, fileinput - -def urlify_string(s): - urls = r'(http|telnet|gopher|file|wais|ftp)' - - ltrs = r'\w'; - gunk = r'/#~:.?+=&%@!\-' - punc = r'.:?\-' - any = ltrs + gunk + punc - - pat = re.compile(r""" - \b # start at word boundary - ( # begin \1 { - %(urls)s : # need resource and a colon - [%(any)s] +? # followed by one or more - # of any valid character, but - # be conservative and take only - # what you need to.... - ) # end \1 } - (?= # look-ahead non-consumptive assertion - [%(punc)s]* # either 0 or more punctuation - [^%(any)s] # followed by a non-url char - | # or else - $ # then end of the string - ) - """%locals(), re.VERBOSE | re.IGNORECASE) - return re.sub(pat, r"<A HREF=\1>\1</A>", s) - -if __name__ == "__main__": - for line in fileinput.input(): - print urlify_string(line) - - -# @@PLEAC@@_6.22 -##----------------------------- -# @@INCOMPLETE@@ -# @@INCOMPLETE@@ - -# @@PLEAC@@_6.23 -# The majority of regexes in this section are either partially -# or completely The Wrong Thing to Do. -##----------------------------- -# DON'T DO THIS. Use a Roman Numeral module, etc. (since -# you need one anyway to calculate values) -pat = r"^m*(d?c{0,3}|c[dm])(l?x{0,3}|x[lc])(v?i{0,3}|i[vx])$" -re.match(pat, "mcmlxcvii") -##----------------------------- -txt = "one two three four five" - -# If the words are cleanly delimited just split and rejoin: -word1, word2, rest = txt.split(" ", 2) -print " ".join([word2, word1, rest]) - -# Otherwise: -frompat = r"(\S+)(\s+)(\S+)" -topat = r"\3\2\1" -print re.sub(frompat, topat, txt) - -##----------------------------- -print str.split("=") - -# DON'T DO THIS -pat = r"(\w+)\s*=\s*(.*)\s*$" -print re.match(pat, "key=val").groups() -##----------------------------- -line = "such a very very very very very very very very very very very very very long line" -if len(line) > 80: - process(line) - -# DON'T DO THIS -pat = ".{80,}" -if re.match(pat, line): - process(line) -##----------------------------- -dt = time.strptime("12/11/05 12:34:56", "%d/%m/%y %H:%M:%S") - -# DON'T DO THIS -pat = r"(\d+)/(\d+)/(\d+) (\d+):(\d+):(\d+)" -dt = re.match(pat, "12/11/05 12:34:56").groups() -##----------------------------- -txt = "/usr/bin/python" -print txt.replace("/usr/bin", "/usr/local/bin") -# Alternatively for file operations use os.path, shutil, etc. - -# DON'T DO THIS -print re.sub("/usr/bin", "/usr/local/bin", txt) -##----------------------------- -import re - -def unescape_hex(matchobj): - return chr(int(matchobj.groups(0)[0], 16)) -txt = re.sub(r"%([0-9A-Fa-f][0-9A-Fa-f])", unescape_hex, txt) - -# Assuming that the hex escaping is well-behaved, an alternative is: -def unescape_hex(seg): - return chr(int(seg[:2], 16)) + seg[2:] - -segs = txt.split("%") -txt = segs[0] + "".join(unescape_hex(seg) for seg in segs[1:]) -##----------------------------- -txt = re.sub(r""" - /\* # Match the opening delimiter - .*? # Match a minimal number of characters - \*/ # Match the closing delimiter - """, "", txt, re.VERBOSE) -##----------------------------- -txt.strip() - -# DON'T DO THIS -txt = re.sub(r"^\s+", "", txt) -txt = re.sub(r"\s+$", "", txt) -##----------------------------- -txt.replace("\\n", "\n") - -# DON'T DO THIS -txt = re.sub("\\n", "\n", txt) -##----------------------------- -txt = re.sub("^.*::", "") -##----------------------------- -import socket -socket.inet_aton(txt) # Will raise an error if incorrect - -# DON'T DO THIS. -octseg =r"([01]?\d\d|2[0-4]\d|25[0-5])" -dot = r"\." -pat = "^" + octseg + dot + octseg + dot + octseg + dot + octseg + "$" - -if not re.match(pat, txt, re.VERBOSE) - raise ValueError - -# Defitely DON'T DO THIS. -pat = r"""^([01]?\d\d|2[0-4]\d|25[0-5])\.([01]?\d\d|2[0-4]\d|25[0-5])\. - ([01]?\d\d|2[0-4]\d|25[0-5])\.([01]?\d\d|2[0-4]\d|25[0-5])$""" -##----------------------------- -fname = os.path.basename(path) - -# DON'T DO THIS. -fname = re.sub("^.*/", "", path) -##----------------------------- -import os -try: - tc = os.environ["TERMCAP"] -except KeyError: - cols = 80 -else: - cols = re.match(":co#(\d+):").groups(1) -##----------------------------- -# (not quite equivalent to the Perl version) -name = os.path.basename(sys.argv[0]) - -# DON'T DO THIS. -name = re.sub("^.*/", "", sys.argv[0]) -##----------------------------- -if sys.platform != "linux": - raise SystemExit("This isn't Linux") -##----------------------------- -txt = re.sub(r"\n\s+", " ", txt) - -# In many cases you could just use: -txt = txt.replace("\n", " ") -##----------------------------- -nums = re.findall(r"\d+\.?\d*|\.\d+", txt) -##----------------------------- -# If the words are clearly delimited just use: -capwords = [word for word in txt.split() if word.isupper()] - -# Otherwise -capwords = [word for word in re.findall(r"\b(\S+)\b", txt) if word.isupper()] - -# (probably) DON'T DO THIS. -capwords = re.findall(r"(\b[^\Wa-z0-9_]+\b)", txt) -##----------------------------- -# If the words are clearly delimited just use: -lowords = [word for word in txt.split() if word.islower()] - -# Otherwise -lowords = [word for word in re.findall(r"\b(\S+)\b", txt) if word.islower()] - -# (probably) DON'T DO THIS. -lowords = re.findall(r"(\b[^\WA-Z0-9_]+\b)", txt) -##----------------------------- -# If the words are clearly delimited just use: -icwords = [word for word in txt.split() if word.istitle()] - -# Otherwise -icwords = [word for word in re.finditer(r"\b(\S+)\b") if word.istitle()] - -# DON'T DO THIS. -icwords = re.findall(r"(\b[^\Wa-z0-9_][^\WA-Z0-9_]*\b)", txt) -##----------------------------- -# DON'T DO THIS - use HTMLParser, etc. -links = re.findall(r"""<A[^>]+?HREF\s*=\s*["']?([^'" >]+?)[ '"]?>""", txt) -##----------------------------- -names = txt.split() -if len(names) == 3: - initial = names[1][0] -else: - initial = "" - -# DON'T DO THIS. -pat = "^\S+\s+(\S)\S*\s+\S" -try: - initial = re.match(pat, txt).group(1) -except AttributeError: - initial = "" -##----------------------------- -txt = re.sub('"([^"]*)"', "``\1''", txt) -##----------------------------- -sentences = [elem[0] for elem in re.findall(r"(.*?[!?.])( |\Z)", s)] -##----------------------------- -import time -dt = time.strptime(txt, "%Y-%m-%d") - -# DON'T DO THIS. -year, month, day = re.match(r"(\d{4})-(\d\d)-(\d\d)", txt).groups() -##----------------------------- -pat = r""" - ^ - (?: - 1 \s (?: \d\d\d \s)? # 1, or 1 and area code - | # ... or ... - \(\d\d\d\) \s # area code with parens - | # ... or ... - (?: \+\d\d?\d? \s)? # optional +country code - \d\d\d ([\s\-]) # and area code - ) - \d\d\d (\s|\1) # prefix (and area code separator) - \d\d\d\d # exchange - $ - """ -re.match(pat, txt, re.VERBOSE) -##----------------------------- -re.match(r"\boh\s+my\s+gh?o(d(dess(es)?|s?)|odness|sh)\b", txt, re.IGNORECASE) -##----------------------------- -for line in file(fname, "Ur"): #Universal newlines - process(line) - -# DON'T DO THIS -lines = [re.sub(r"^([^\012\015]*)(\012\015?|\015\012?)", "", line) - for line in file(fname)] -##----------------------------- - - -# @@PLEAC@@_7.0 -for line in open("/usr/local/widgets/data"): - if blue in line: - print line[:-1] -#--------- -import sys, re -pattern = re.compile(r"\d") -for line in sys.stdin: - if not pattern.search(line): - sys.stderr.write("No digit found.\n") - sys.stdout.write("Read: " + line) -sys.stdout.close() -#--------- -logfile = open("/tmp/log", "w") -#--------- -logfile.close() -#--------- -print>>logfile, "Countdown initiated ..." -print "You have 30 seconds to reach minimum safety distance." - -# DONT DO THIS -import sys -old_output, sys.stdout = sys.stdout, logfile -print "Countdown initiated ..." -sys.stdout = old_output -print "You have 30 seconds to reach minimum safety distance." -#--------- - -# @@PLEAC@@_7.1 -# Python's open() function somewhat covers both perl's open() and -# sysopen() as it has optional arguments for mode and buffering. -source = open(path) -sink = open(path, "w") -#--------- -# NOTE: almost no one uses the low-level os.open and os.fdopen -# commands, so their inclusion here is just silly. If -# os.fdopen(os.open(...)) were needed often, it would be turned -# into its own function. Instead, I'll use 'fd' to hint that -# os.open returns a file descriptor -import os -source_fd = os.open(path, os.O_RDONLY) -source = os.fdopen(fd) -sink_fd = os.open(path, os.O_WRONLY) -sink = os.fdopen(sink_fd) -#--------- -myfile = open(filename, "w") -fd = os.open(filename, os.O_WRONLY | os.O_CREAT) -myfile = open(filename, "r+") -#--------- -fd = os.open(name, flags) -fd = os.open(name, flags, mode) -#--------- -myfile = open(path) -fd = os.open(path, os.O_RDONLY) -#----------------------------- -myfile = open(path, "w") -fd = os.open(path, os.O_WRONLY|os.O_TRUNC|os.O_CREAT) -fd = os.open(path, os.O_WRONLY|os.O_TRUNC|os.O_CREAT, 0600) -#----------------------------- -fd = os.open(path, os.O_WRONLY|os.O_EXCL|os.O_CREAT) -fd = os.open(path, os.O_WRONLY|os.O_EXCL|os.O_CREAT, 0600) -#----------------------------- -myfile = open(path, "a") -fd = os.open(path, os.O_WRONLY|os.O_APPEND|os.O_CREAT) -fd = os.open(path, os.O_WRONLY|os.O_APPEND|s.O_CREAT, 0600) -#----------------------------- -fd = os.open(path, os.O_WRONLY|os.O_APPEND) -#----------------------------- -myfile = open(path, "rw") -fd = os.open(path, os.O_RDWR) -#----------------------------- -fd = os.open(path, os.O_RDWR|os.O_CREAT) -fd = os.open(path, os.O_RDWR|os.O_CREAT, 0600) -#----------------------------- -fd = os.open(path, os.O_RDWR|os.O_EXCL|os.O_CREAT) -fd = os.open(path, os.O_RDWR|os.O_EXCL|os.O_CREAT, 0600) -#----------------------------- - -# @@PLEAC@@_7.2 -# Nothing different needs to be done with Python - -# @@PLEAC@@_7.3 -import os -filename = os.path.expanduser(filename) - -# @@PLEAC@@_7.4 -myfile = open(filename) # raise an exception on error - -try: - myfile = open(filename) -except IOError, err: - raise AssertionError("Couldn't open %s for reading : %s" % - (filename, err.strerror)) - -# @@PLEAC@@_7.5 -import tempfile - -myfile = tempfile.TemporaryFile() - -#----------------------------- -# NOTE: The TemporaryFile() call is much more appropriate -# I would not suggest using this code for real work. -import os, tempfile - -while True: - name = os.tmpnam() - try: - fd = os.open(name, os.O_RDWR|os.O_CREAT|os.O_EXCL) - break - except os.error: - pass -myfile = tempfile.TemporaryFileWrapper(os.fdopen(fd), name) - -# now go on to use the file ... -#----------------------------- -import os -while True: - tmpname = os.tmpnam() - fd = os.open(tmpnam, os.O_RDWR | os.O_CREAT | os.O_EXCL) - if fd: - tmpfile = os.fdopen(fd) - break - -os.remove(tmpnam) - -#----------------------------- -import tempfile - -myfile = tempfile.TemporaryFile(bufsize = 0) -for i in range(10): - print>>myfile, i -myfile.seek(0) -print "Tmp file has:", myfile.read() -#----------------------------- - -# @@PLEAC@@_7.6 -DATA = """\ -your data goes here -""" -for line in DATA.split("\n"): - pass # process the line - -# @@PLEAC@@_7.7 - -for line in sys.stdin: - pass # do something with the line - -# processing a list of files from commandline -import fileinput -for line in fileinput.input(): - do something with the line - -#----------------------------- -import sys - -def do_with(myfile): - for line in myfile: - print line[:-1] - -filenames = sys.argv[1:] -if filenames: - for filename in filenames: - try: - do_with(open(filename)) - except IOError, err: - sys.stderr.write("Can't open %s: %s\n" % (filename, err.strerror)) - continue -else: - do_with(sys.stdin) - -#----------------------------- -import sys, glob -ARGV = sys.argv[1:] or glob.glob("*.[Cch]") -#----------------------------- -# NOTE: the getopt module is the prefered mechanism for reading -# command line arguments -import sys -args = sys.argv[1:] -chop_first = 0 - -if args and args[0] == "-c": - chop_first += 1 - args = args[1:] - -# arg demo 2: Process optional -NUMBER flag - -# NOTE: You just wouldn't process things this way for Python, -# but I'm trying to preserve the same semantics. - -import sys, re -digit_pattern = re.compile(r"-(\d+)$") - -args = sys.argv[1:] -if args: - match = digit_pattern.match(args[0]) - if match: - columns = int(match.group(1)) - args = args[1:] - -# NOTE: here's the more idiomatic way, which also checks -# for the "--" or a non "-" argument to stop processing - -args = sys.argv[1:] -for i in range(len(args)): - arg = args[i] - if arg == "--" or not arg.startwith("-"): - break - if arg[1:].isdigit(): - columns = int(arg[1:]) - continue - - - -# arg demo 3: Process clustering -a, -i, -n, or -u flags -import sys, getopt -try: - args, filenames = getopt.getopt(sys.argv[1:], "ainu") -except getopt.error: - raise SystemExit("usage: %s [-ainu] [filenames] ..." % sys.argv[0]) - -append = ignore_ints = nostdout = unbuffer = 0 -for k, v in args: - if k == "-a": append += 1 - elif k == "-i": ignore_ints += 1 - elif k == "-n": nostdout += 1 - elif k == "-u": unbuffer += 1 - else: - raise AssertionError("Unexpected argument: %s" % k) - -#----------------------------- -# Note: Idiomatic Perl get translated to idiomatic Python -import fileinput -for line in fileinput.input(): - sys.stdout.write("%s:%s:%s" % - (fileinput.filename(), fileinput.filelineno(), line)) -#----------------------------- -#!/usr/bin/env python -# findlogin1 - print all lines containing the string "login" -for line in fileinput.input(): # loop over files on command line - if line.find("login") != -1: - sys.stdout.write(line) - -#----------------------------- -#!/usr/bin/env python -# lowercase - turn all lines into lowercase -### NOTE: I don't know how to do locales in Python -for line in fileinput.input(): # loop over files on command line - sys.stdout.write(line.lower()) - -#----------------------------- -#!/usr/bin/env python -# NOTE: The Perl code appears buggy, in that "Q__END__W" is considered -# to be a __END__ and words after the __END__ on the same line -# are included in the count!!! -# countchunks - count how many words are used. -# skip comments, and bail on file if __END__ -# or __DATA__ seen. -chunks = 0 -for line in fileinput.input(): - for word in line.split(): - if word.startswith("#"): - continue - if word in ("__DATA__", "__END__"): - fileinput.close() - break - chunks += 1 -print "Found", chunks, "chunks" - - -# @@PLEAC@@_7.8 -import shutil - -old = open("old") -new = open("new","w") - -for line in old: - new.writeline(line) -new.close() -old.close() - -shutil.copyfile("old", "old.orig") -shutil.copyfile("new", "old") - -# insert lines at line 20: -for i, line in enumerate(old): - if i == 20: - print>>new, "Extra line 1\n" - print>>new, "Extra line 2\n" - print>>new, line - - -# or delete lines 20 through 30: -for i, line in enumerate(old): - if 20 <= i <= 30: - continue - print>>new, line - - -# @@PLEAC@@_7.9 -# modifying with "-i" commandline switch is a perl feature -# python has fileinput -import fileinput, sys, time -today = time.strftime("%Y-%m-%d",time.localtime()) -for line in fileinput.input(inplace=1, backup=".orig"): - sys.stdout.write(line.replace("DATE",today)) - -# set up to iterate over the *.c files in the current directory, -# editing in place and saving the old file with a .orig extension. -import glob, re -match = re.compile("(?<=[pP])earl") -files = fileinput.FileInput(glob.glob("*.c"), inplace=1, backup=".orig") -while True: - line = files.readline() - sys.stderr.write(line) - if not line: - break - if files.isfirstline(): - sys.stdout.write("This line should appear at the top of each file\n") - sys.stdout.write(match.sub("erl",line)) - - -# @@PLEAC@@_7.10 -#----------------------------- -myfile = open(filename, "r+") -data = myfile.read() -# change data here -myfile.seek(0, 0) -myfile.write(data) -myfile.truncate(myfile.tell()) -myfile.close() -#----------------------------- -myfile = open(filename, "r+") -data = [process(line) for line in myfile] -myfile.seek(0, 0) -myfile.writelines(data) -myfile.truncate(myfile.tell()) -myfile.close() -#----------------------------- - -# @@PLEAC@@_7.11 - -import fcntl -myfile = open(somepath, 'r+') -fcntl.flock(myfile, fcntl.LOCK_EX) -# update file, then... -myfile.close() -#----------------------------- -fcntl.LOCK_SH -fcntl.LOCK_EX -fcntl.LOCK_NB -fcntl.LOCK_UN -#----------------------------- -import warnings -try: - fcntl.flock(myfile, fcntl.LOCK_EX|fcntl.LOCK_NB) -except IOError: - warnings.warn("can't immediately write-lock the file ($!), blocking ...") - fcntl.flock(myfile, fcntl.LOCK_EX) -#----------------------------- -fcntl.flock(myfile, fcntl.LOCK_UN) -#----------------------------- -# option "r+" instead "w+" stops python from truncating the file on opening -# when another process might well hold an advisory exclusive lock on it. -myfile = open(somepath, "r+") -fcntl.flock(myfile, fcntl.LOCK_EX) -myfile.seek(0, 0) -myfile.truncate(0) -print>>myfile, "\n" # or myfile.write("\n") -myfile.close() -#----------------------------- - -# @@PLEAC@@_7.12 -# Python doesn't have command buffering. Files can have buffering set, -# when opened: -myfile = open(filename, "r", buffering=0) #Unbuffered -myfile = open(filename, "r", buffering=1) #Line buffered -myfile = open(filename, "r", buffering=100) #Use buffer of (approx) 100 bytes -myfile = open(filename, "r", buffering=-1) #Use system default - -myfile.flush() # Flush the I/O buffer - -# stdout is treated as a file. If you ever need to flush it, do so: -import sys -sys.stdout.flush() - -# DON'T DO THIS. Use urllib, etc. -import socket -mysock = socket.socket() -mysock.connect(('www.perl.com', 80)) -# mysock.setblocking(True) -mysock.send("GET /index.html http/1.1\n\n") -f = mysock.makefile() -print "Doc is:" -for line in f: - print line[:-1] - -# @@PLEAC@@_7.13 -import select -while True: - rlist, wlist, xlist = select.select([file1, file2, file3], [], [], 0) - for r in rlist: - pass # Do something with the file handle - -# @@PLEAC@@_7.14 -# @@SKIP@@ Use select.poll() on Unix systems. -# @@INCOMPLETE@@ -# @@INCOMPLETE@@ - -# @@PLEAC@@_7.15 -# @@INCOMPLETE@@ -# @@INCOMPLETE@@ - -# @@PLEAC@@_7.16 -# NOTE: this is all much easier in Python -def subroutine(myfile): - print>>myfile, "Hello, file" - -variable = myfile -subroutine(variable) - -# @@PLEAC@@_7.17 -# @@INCOMPLETE@@ -# @@INCOMPLETE@@ - -# @@PLEAC@@_7.18 -for myfile in files: - print>>myfile, stuff_to_print - -# NOTE: This is unix specific -import os -file = os.popen("tee file1 file2 file3 >/dev/null", "w") -print>>myfile, "whatever" - -# NOTE: the "make STDOUT go to three files" is bad programming style -import os, sys -sys.stdout.file = os.popen("tee file1 file2 file3", "w") -print "whatever" -sys.stdout.close() - -# You could use a utility object to redirect writes: -class FileDispatcher(object): - def __init__(self, *files): - self.files = files - - def write(self, msg): - for f in self.files: - f.write(msg) - - def close(self): - for f in self.files: - f.close() - -x = open("C:/test1.txt", "w") -y = open("C:/test2.txt", "w") -z = open("C:/test3.txt", "w") - -fd = FileDispatcher(x, y, z) -print>>fd, "Foo" # equiv to fd.write("Foo"); fd.write("\n") -print>>fd, "Testing" -fd.close() - -# @@PLEAC@@_7.19 -import os -myfile = os.fdopen(fdnum) # open the descriptor itself -myfile = os.fdopen(os.dup(fdnum)) # open to a copy of the descriptor - -### -outcopy = os.fdopen(os.dup(sys.stdin.fileno()), "w") -incopy = os.fdopen(os.dup(sys.stdin.fileno()), "r") - -# @@PLEAC@@_7.20 -original = open("C:/test.txt") -alias = original -alias.close() -print original.closed -#=>True - -import copy - -original = open("C:/test.txt") -dupe = copy.copy(original) -dupe.close() -print original.closed -#=>False - -# DON'T DO THIS. -import sys -oldstderr = sys.stderr -oldstdout = sys.stdout - -sys.stderr = open("C:/stderrfile.txt") -sys.stdout = open("C:/stdoutfile.txt") - -print "Blah" # Will be written to C:/stdoutfile.txt -sys.stdout.close() - -sys.stdout = oldstdout -sys.stderr = oldstderr - - -# @@PLEAC@@_7.21 -# @@INCOMPLETE@@ -# @@INCOMPLETE@@ - -# @@PLEAC@@_7.22 -# On Windows: -import msvcrt -myfile.seek(5, 0) -msvcrt.locking(myfile.fileno(), msvcrt.LK_NBLCK, 3) - -# On Unix: -import fcntl -fcntl.lockf(myfile.fileno(), fcntl.LOCK_EX | fcntl.LOCK_NB, 3, 5) - - -# ^^PLEAC^^_8.0 -#----------------------------- -for line in DATAFILE: - line = line.rstrip() - size = len(line) - print size # output size of line - -#----------------------------- -for line in datafile: - print length(line.rstrip()) # output size of line -#----------------------------- -lines = datafile.readlines() -#----------------------------- -whole_file = myfile.read() -#----------------------------- -## No direct equivalent in Python -#% perl -040 -e '$word = <>; print "First word is $word\n";' -#----------------------------- -## No direct equivalent in Python -#% perl -ne 'BEGIN { $/="%%\n" } chomp; print if /Unix/i' fortune.dat -#----------------------------- -print>>myfile, "One", "two", "three" # "One two three" -print "Baa baa black sheep." # Sent to default output file -#----------------------------- -buffer = myfile.read(4096) -rv = len(buffer) -#----------------------------- -myfile.truncate(length) -open("/tmp/%d.pid" % os.getpid(), "a").truncate(length) -#----------------------------- -pos = myfile.tell() -print "I'm", pos, "bytes from the start of DATAFILE." -#----------------------------- -logfile.seek(0, 2) # Seek to the end -datafile.seek(pos) # Seek to a given byte -outfile.seek(-20, 1) # Seek back 20 bytes -#----------------------------- -written = os.write(datafile.fileno(), mystr) -if written != len(mystr): - warnings.warn("only read %s bytes, not %s" % (written, len(mystr))) -#----------------------------- -pos = os.lseek(myfile.fileno(), 0, 1) # don't change position -#----------------------------- - - -# ^^PLEAC^^_8.1 -def ContReader(infile): - lines = [] - for line in infile: - line = line.rstrip() - if line.endswith("\\"): - lines.append(line[:-1]) - continue - lines.append(line) - yield "".join(lines) - lines = [] - if lines: - yield "".join(lines) - -for line in ContReader(datafile): - pass # process full record in 'line' here - -# ^^PLEAC^^_8.2 -import os -count = int(os.popen("wc -l < " + filename).read()) -#----------------------------- -for count, line in enumerate(open(filename)): - pass -count += 1 # indexing is zero based -#----------------------------- -myfile = open(filename) -count = 0 -for line in myfile: - count += 1 -# 'count' now holds the number of lines read -#----------------------------- -myfile = open(filename) -count = 0 -while True: - line = myfile.readline() - if not line: - break - count += 1 -#----------------------------- -count = 0 -while True: - s = myfile.read(2**16) - count += s.count("\n") -#----------------------------- -for line, count in zip(open(filename), xrange(1, sys.maxint)): - pass -# 'count' now holds the number of lines read -#----------------------------- -import fileinput -fi = fileinput.FileInput(filename) -while fi.readline(): pass - -count = fi.lineno() -#----------------------------- -def SepReader(infile, sep = "\n\n"): - text = infile.read(10000) - if not text: - return - while True: - fields = text.split(sep) - for field in fields[:-1]: - yield field - text = fields[-1] - new_text = infile.read(10000) - if not new_text: - yield text - break - text += new_text - -para_count = 0 -for para in SepReader(open(filename)): - para_count += 1 -# FIXME: For my test case (Python-pre2.2 README from CVS) this -# returns 175 paragraphs while Perl returns 174. -#----------------------------- - - -# ^^PLEAC^^_8.3 -for line in sys.stdin: - for word in line.split(): - pass # do something with 'chunk' -#----------------------------- -pat = re.compile(r"(\w[\w'-]*)") -for line in sys.stdin: - pos = 0 - while True: - match = pat.search(line, pos) - if not match: - break - pos = match.end(1) - # do something with match.group(1) - -# EXPERIMENTAL in the sre implementation but -# likely to be included in future (post-2.2) releases. -pat = re.compile(r"(\w[\w'-]*)") -for line in sys.stdin: - scanner = pat.scanner(line) - while True: - match = scanner.search() - if not match: - break - # do something with match.group(1) - - -#----------------------------- -# Make a word frequency count -import fileinput, re -pat = re.compile(r"(\w[\w'-]*)") -seen = {} -for line in fileinput.input(): - pos = 0 - while True: - match = pat.search(line, pos) - if not match: - break - pos = match.end(1) - text = match.group(1).lower() - seen[text] = seen.get(text, 0) + 1 - -# output dict in a descending numeric sort of its values -for text, count in sorted(seen.items, key=lambda item: item[1]): - print "%5d %s" % (count, text) - -#----------------------------- -# Line frequency count -import fileinput, sys -seen = {} -for line in fileinput.input(): - text = line.lower() - seen[text] = seen.get(text, 0) + 1 - -for text, count in sorted(seen.items, key=lambda item: item[1]): - sys.stdout.write("%5d %s" % (count, text)) - -#----------------------------- - - -# ^^PLEAC^^_8.4 -lines = myfile.readlines() -while lines: - line = lines.pop() - # do something with 'line' - -#----------------------------- -for line in reversed(myfile): - pass # do something with line -#----------------------------- -for i in range(len(lines)): - line = lines[-i] -#----------------------------- -for paragraph in sorted(SepReader(infile)): - pass # do something -#----------------------------- - - - -# ^^PLEAC^^_8.5 -import time -while True: - for line in infile: - pass # do something with the line - time.sleep(SOMETIME) - infile.seek(0, 1) -#----------------------------- -import time -naptime = 1 - -logfile = open("/tmp/logfile") -while True: - for line in logfile: - print line.rstrip() - time.sleep(naptime) - infile.seek(0, 1) -#----------------------------- -while True: - curpos = logfile.tell() - while True: - line = logfile.readline() - if not line: - break - curpos = logfile.tell() - sleep(naptime) - logfile.seek(curpos, 0) # seek to where we had been -#----------------------------- -import os -if os.stat(LOGFILENAME).st_nlink == 0: - raise SystemExit -#----------------------------- - - -# ^^PLEAC^^_8.6 -import random, fileinput -text = None -for line in fileinput.input(): - if random.randrange(fileinput.lineno()) == 0: - text = line -# 'text' is the random line -#----------------------------- -# XXX is the perl code correct? Where is the fortunes file opened? -import sys -adage = None -for i, rec in enumerate(SepReader(open("/usr/share/games/fortunes"), "%\n")): - if random.randrange(i+1) == 0: - adage = rec -print adage -#----------------------------- - - -# ^^PLEAC^^_8.7 -import random -lines = data.readlines() -random.shuffle(lines) -for line in lines: - print line.rstrip() -#----------------------------- - - - -# ^^PLEAC^^_8.8 -# using efficient caching system -import linecache -linecache.getline(filename, DESIRED_LINE_NUMBER) - -# or doing it more oldskool -lineno = 0 -while True: - line = infile.readline() - if not line or lineno == DESIRED_LINE_NUMBER: - break - lineno += 1 -#----------------------------- -lines = infile.readlines() -line = lines[DESIRED_LINE_NUMBER] -#----------------------------- -for i in range(DESIRED_LINE_NUMBER): - line = infile.readline() - if not line: - break -#----------------------------- - -## Not sure what this thing is doing. Allow fast access to a given -## line number? - -# usage: build_index(*DATA_HANDLE, *INDEX_HANDLE) - -# ^^PLEAC^^_8.9 -# given $RECORD with field separated by PATTERN, -# extract @FIELDS. -fields = re.split(pattern_string, text) -#----------------------------- -pat = re.compile(pattern_string) -fields = pat.split(text) -#----------------------------- -re.split(r"([+-])", "3+5-2") -#----------------------------- -[3, '+', 5, '-', 2] -#----------------------------- -fields = record.split(":") -#----------------------------- -fields = re.split(r":", record) -#----------------------------- -fields = re.split(r"\s+", record) -#----------------------------- -fields = record.split(" ") -#----------------------------- - - -# ^^PLEAC^^_8.10 -myfile = open(filename, "r") -prev_pos = pos = 0 -while True: - line = myfile.readline() - if not line: - break - prev_pos = pos - pos = myfile.tell() -myfile = open(filename, "a") -myfile.truncate(prev_pos) -#----------------------------- - - - -# ^^PLEAC^^_8.11 -open(filename, "rb") -open(filename, "wb") -#----------------------------- -gifname = "picture.gif" -gif_file = open(gifname, "rb") - -# Don't think there's an equivalent for these in Python -#binmode(GIF); # now DOS won't mangle binary input from GIF -#binmode(STDOUT); # now DOS won't mangle binary output to STDOUT - -#----------------------------- -while True: - buff = gif.read(8 * 2**10) - if not buff: - break - sys.stdout.write(buff) -#----------------------------- - - - -# ^^PLEAC^^_8.12 -address = recsize * recno -myfile.seek(address, 0) -buffer = myfile.read(recsize) -#----------------------------- -address = recsize * (recno-1) -#----------------------------- - - - -# ^^PLEAC^^_8.13 -import posixfile -address = recsize * recno -myfile.seek(address) -buffer = myfile.read(recsize) -# ... work with the buffer, then turn it back into a string and ... -myfile.seek(-recsize, posixfile.SEEK_CUR) -myfile.write(buffer) -myfile.close() -#----------------------------- -## Not yet implemented -# weekearly -- set someone's login date back a week -# @@INCOMPLETE@@ - - -# ^^PLEAC^^_8.14 -## Note: this isn't optimal -- the 's+=c' may go O(N**2) so don't -## use for large strings. -myfile.seek(addr) -s = "" -while True: - c = myfile.read(1) - if not c or c == "\0": - break - s += c -#----------------------------- -myfile.seek(addr) -offset = 0 -while True: - s = myfile.read(1000) - x = s.find("\0") - if x != -1: - offset += x - break - offset += len(s) - if len(s) != 1000: # EOF - break -myfile.seek(addr) -s = myfile.read(offset - 1) -myfile.read(1) - -#----------------------------- -## Not Implemented -# bgets - get a string from an address in a binary file -#----------------------------- -#!/usr/bin/perl -# strings - pull strings out of a binary file -import re, sys - -## Assumes SepReader from above - -pat = re.compile(r"([\040-\176\s]{4,})") -for block in SepReader(sys.stdin, "\0"): - pos = 0 - while True: - match = pat.search(block, pos) - if not match: - break - print match.group(1) - pos = match.end(1) -#----------------------------- - - -# @@PLEAC@@_8.15 - -# RECORDSIZE is the length of a record, in bytes. -# TEMPLATE is the unpack template for the record -# FILE is the file to read from -# FIELDS is a tuple, one element per field -import struct -RECORDSIZE= struct.calcsize(TEMPLATE) -while True: - record = FILE.read(RECORDSIZE): - if len(record)!=RECORDSIZE: - raise "short read" - FIELDS = struct.unpack(TEMPLATE, record) -# ---- - - -# ^^PLEAC^^_8.16 -# NOTE: to parse INI file, see the stanard ConfigParser module. -import re -pat = re.compile(r"\s*=\s*") -for line in config_file: - if "#" in line: # no comments - line = line[:line.index("#")] - line = line.strip() # no leading or trailing white - if not line: # anything left? - continue - m = pat.search(line) - var = line[:m.start()] - value = line[m.end():] - User_Preferences[var] = value - - -# ^^PLEAC^^_8.17 -import os - -mode, ino, dev, nlink, uid, gid, size, \ -atime, mtime, ctime = os.stat(filename) - -mode &= 07777 # discard file type info - -#----------------------------- -info = os.stat(filename) -if info.st_uid == 0: - print "Superuser owns", filename -if info.st_atime > info.st_mtime: - print filename, "has been read since it was written." -#----------------------------- -import os -def is_safe(path): - info = os.stat(path) - - # owner neither superuser nor me - # the real uid is in stored in the $< variable - if info.st_uid not in (0, os.getuid()): - return False - - # check whether group or other can write file. - # use 066 to detect either reading or writing - if info.st_mode & 022: # someone else can write this - if not os.path.isdir(path): # non-directories aren't safe - return False - # but directories with the sticky bit (01000) are - if not (info.st_mode & 01000): - return False - return True -#----------------------------- -## XXX What is '_PC_CHOWN_RESTRICTED'? - -def is_verysafe(path): - terms = [] - while True: - path, ending = os.path.split(path) - if not ending: - break - terms.insert(0, ending) - for term in terms: - path = os.path.join(path, term) - if not is_safe(path): - return False - return True -#----------------------------- - -# Program: tctee -# Not Implemented (requires reimplementing Perl's builtin '>>', '|', -# etc. semantics) - -# @@PLEAC@@_8.18 -#!/usr/bin/python -# tailwtmp - watch for logins and logouts; -# uses linux utmp structure, from /usr/include/bits/utmp.h - -# /* The structure describing an entry in the user accounting database. */ -# struct utmp -# { -# short int ut_type; /* Type of login. */ -# pid_t ut_pid; /* Process ID of login process. */ -# char ut_line[UT_LINESIZE]; /* Devicename. */ -# char ut_id[4]; /* Inittab ID. */ -# char ut_user[UT_NAMESIZE]; /* Username. */ -# char ut_host[UT_HOSTSIZE]; /* Hostname for remote login. */ -# struct exit_status ut_exit; /* Exit status of a process marked -# as DEAD_PROCESS. */ -# long int ut_session; /* Session ID, used for windowing. */ -# struct timeval ut_tv; /* Time entry was made. */ -# int32_t ut_addr_v6[4]; /* Internet address of remote host. */ -# char __unused[20]; /* Reserved for future use. */ -# }; - -# /* Values for the `ut_type' field of a `struct utmp'. */ -# #define EMPTY 0 /* No valid user accounting information. */ -# -# #define RUN_LVL 1 /* The system's runlevel. */ -# #define BOOT_TIME 2 /* Time of system boot. */ -# #define NEW_TIME 3 /* Time after system clock changed. */ -# #define OLD_TIME 4 /* Time when system clock changed. */ -# -# #define INIT_PROCESS 5 /* Process spawned by the init process. */ -# #define LOGIN_PROCESS 6 /* Session leader of a logged in user. */ -# #define USER_PROCESS 7 /* Normal process. */ -# #define DEAD_PROCESS 8 /* Terminated process. */ -# -# #define ACCOUNTING 9 - -import time -import struct -import os - -class WTmpRecord: - fmt = "hI32s4s32s256siili4l20s"; - _fieldnames = ["type","PID","Line","inittab","User","Hostname", - "exit_status", "session", "time", "addr" ] - def __init__(self): - self._rec_size = struct.calcsize(self.fmt) - def size(self): - return self._rec_size - def unpack(self, bin_data): - rec = struct.unpack(self.fmt, bin_data) - self._rec = [] - for i in range(len(rec)): - if i in (2,3,4,5): - # remove character zeros from strings - self._rec.append( rec[i].split("\0")[0] ) - else: - self._rec.append(rec[i]) - return self._rec - def fieldnames(self): - return self._fieldnames - def __getattr__(self,name): - return self._rec[self._fieldnames.index(name)] - -rec = WTmpRecord() -f = open("/var/log/wtmp","rb") -f.seek(0,2) -while True: - while True: - bin = f.read(rec.size()) - if len(bin) != rec.size(): - break - rec.unpack(bin) - if rec.type != 0: - print " %1d %-8s %-12s %-24s %-20s %5d %08x" % \ - (rec.type, rec.User, rec.Line, - time.strftime("%a %Y-%m-%d %H:%M:%S",time.localtime(rec.time)), - rec.Hostname, rec.PID, rec.addr) - time.sleep(1) -f.close() - -# @@PLEAC@@_8.19 -# @@INCOMPLETE@@ -# @@INCOMPLETE@@ - -# @@PLEAC@@_8.20 -#!/usr/bin/python -# laston - find out when given user last logged on -import sys -import struct -import pwd -import time -import re - -f = open("/var/log/lastlog","rb") - -fmt = "L32s256s" -rec_size = struct.calcsize(fmt) - -for user in sys.argv[1:]: - if re.match(r"^\d+$", user): - user_id = int(user) - else: - try: - user_id = pwd.getpwnam(user)[2] - except: - print "no such uid %s" % (user) - continue - f.seek(rec_size * user_id) - bin = f.read(rec_size) - if len(bin) == rec_size: - data = struct.unpack(fmt, bin) - if data[0]: - logged_in = "at %s" % (time.strftime("%a %H:%M:%S %Y-%m-%d", - time.localtime(data[0]))) - line = " on %s" % (data[1]) - host = " from %s" % (data[2]) - else: - logged_in = "never logged in" - line = "" - host = "" - print "%-8s UID %5d %s%s%s" % (user, user_id, logged_in, line, host) - else: - print "Read failed." -f.close() - - -# ^^PLEAC^^_9.0 -#----------------------------- -entry = os.stat("/usr/bin/vi") -#----------------------------- -entry = os.stat("/usr/bin") -#----------------------------- -entry = os.stat(INFILE.name) -#----------------------------- -entry = os.stat("/usr/bin/vi") -ctime = entry.st_ino -size = entry.st_size -#----------------------------- -f = open(filename) - -f.seek(0, 2) -if not f.tell(): - raise SystemExit("%s doesn't have text in it."%filename) -#----------------------------- - -for filename in os.listdir("/usr/bin"): - print "Inside /usr/bin is something called", filename -#----------------------------- - -# ^^PLEAC^^_9.1 -#----------------------------- -fstat = os.stat(filename) -readtime = fstat.st_atime -writetime = fstat.st_mtime - -os.utime(filename, (newreadtime, newwritetime)) - -#DON'T DO THIS: -readtime, writetime = os.stat(filename)[7:9] -#----------------------------- -SECONDS_PER_DAY = 60 * 60 * 24 -fstat = os.stat(filename) -atime = fstat.st_atime - 7 * SECONDS_PER_DAY -mtime = fstat.st_mtime - 7 * SECONDS_PER_DAY - -os.utime(filename, (atime, mtime)) -#----------------------------- -mtime = os.stat(filename).st_mtime -utime(filename, (time.time(), mtime)) -#----------------------------- -#!/usr/bin/perl -w -# uvi - vi a file without changing its access times - -import sys, os -if len(sys.argv) != 2: - raise SystemExit("usage: uvi filename") -filename = argv[1] -fstat = os.stat(filename) -# WARNING: potential security risk -os.system( (os.environ.get("EDITOR") or "vi") + " " + filename) -os.utime(filename, (fstat.st_atime, fstat.st_mtime)) -#----------------------------- - -# ^^PLEAC^^_9.2 -#----------------------------- -os.remove(filename) - -err_flg = 0 -for filename in filenames: - try: - os.remove(filename) - except OSError, err: - err_flg = 1 -if err_flg: - raise OSError("Couldn't remove all of %s: %s" % (filenames, err)) -#----------------------------- -os.remove(filename) -#----------------------------- -success = 0 -for filename in filenames: - try: - os.remove(filename) - success += 1 - except OSError, err: - pass -if success != len(filenames): - sys.stderr.write("could only delete %d of %d files" % \ - (success, len(filenames))) - -#----------------------------- - -# ^^PLEAC^^_9.3 -#----------------------------- -import shutil -shutil.copy(oldfile, newfile) -#----------------------------- -## NOTE: this doesn't do the same thing as the Perl code, -## eg, handling of partial writes. -infile = open(oldfile) -outfile = open(newfile, "w") - -blksize = 16384 # preferred block size? - -while True: - buf = infile.read(blksize) - if not buf: - break - outfile.write(buf) - -infile.close() -outfile.close() -#----------------------------- -# WARNING: these are insecure - do not use in hostile environments -os.system("cp %s %s" % (oldfile, newfile)) # unix -os.system("copy %s %s" % (oldfile, newfile)) # dos, vms -#----------------------------- -import shutil - -shutil.copy("datafile.dat", "datafile.bak") - -shutil.copy("datafile.new", "datafile.dat") -os.remove("datafile.new") - -#----------------------------- - -# ^^PLEAC^^_9.4 -#----------------------------- -import os -seen = {} - -def do_my_thing(filename): - fstat = os.stat(filename) - key = (fstat.st_ino, fstat.st_dev) - if not seen.get(key): - # do something with filename because we haven't - # seen it before - pass - seen[key] = seen.get(key, 0 ) + 1 - -#----------------------------- -for filename in files: - fstat = os.stat(filename) - key = (fstat.st_ino, fstat.st_dev) - seen.setdefault(key, []).append(filename) - -keys = seen.keys() -keys.sort() -for inodev in keys: - ino, dev = inodev - filenames = seen[inodev] - if len(filenames) > 1: - # 'filenames' is a list of filenames for the same file - pass -#----------------------------- - -# ^^PLEAC^^_9.5 -#----------------------------- -for filename in os.listdir(dirname): - # do something with "$dirname/$file" - pass -#----------------------------- -# XXX No -T equivalent in Python -#----------------------------- -# 'readir' always skipes '.' and '..' on OSes where those are -# standard directory names -for filename in os.listdir(dirname): - pass -#----------------------------- -# XX Not Implemented -- need to know what DirHandle does -# use DirHandle; - -#----------------------------- - -# ^^PLEAC^^_9.6 -#----------------------------- -import glob -filenames = glob.glob("*.c") -#----------------------------- -filenames = [filename for filename in os.listdir(path) if filename.endswith(".c")] -#----------------------------- -import re -allowed_name = re.compile(r"\.[ch]$", re.I).search -filenames = [f for f in os.listdir(path) if allowed_name(f)] -#----------------------------- -import re, os -allowed_name = re.compile(r"\.[ch]$", re.I).search - -fnames = [os.path.join(dirname, fname) - for fname in os.listdir(dirname) - if allowed_name(fname)] -#----------------------------- -dirs = [os.path.join(path, f) - for f in os.listdir(path) if f.isdigit()] -dirs = [d for d in dirs if os.path.isdir(d)] -dirs = sorted(dirs, key=int) # Sort by numeric value - "9" before "11" -#----------------------------- - -# @@PLEAC@@_9.7 -# Processing All Files in a Directory Recursively - -# os.walk is new in 2.3. - -# For pre-2.3 code, there is os.path.walk, which is -# little harder to use. - -#----------------------------- -import os -for root, dirs, files in os.walk(top): - pass # do whatever - -#----------------------------- -import os, os.path -for root, dirs, files in os.walk(top): - for name in dirs: - print os.path.join(root, name) + '/' - for name in files: - print os.path.join(root, name) - -#----------------------------- -import os, os.path -numbytes = 0 -for root, dirs, files in os.walk(top): - for name in files: - path = os.path.join(root, name) - numbytes += os.path.getsize(path) -print "%s contains %s bytes" % (top, numbytes) - -#----------------------------- -import os, os.path -saved_size, saved_name = -1, '' -for root, dirs, files in os.walk(top): - for name in files: - path = os.path.join(root, name) - size = os.path.getsize(path) - if size > saved_size: - saved_size = size - saved_name = path -print "Biggest file %s in %s is %s bytes long" % ( - saved_name, top, saved_size) - -#----------------------------- -import os, os.path, time -saved_age, saved_name = None, '' -for root, dirs, files in os.walk(top): - for name in files: - path = os.path.join(root, name) - age = os.path.getmtime(path) - if saved_age is None or age > saved_age: - saved_age = age - saved_name = path -print "%s %s" % (saved_name, time.ctime(saved_age)) - -#----------------------------- -#!/usr/bin/env python -# fdirs - find all directories -import sys, os, os.path -argv = sys.argv[1:] or ['.'] -for top in argv: - for root, dirs, files in os.walk(top): - for name in dirs: - path = os.path.join(root, name) - print path - - -# ^^PLEAC^^_9.8 -#----------------------------- -# DeleteDir - remove whole directory trees like rm -r -import shutil -shutil.rmtree(path) - -# DON'T DO THIS: -import os, sys -def DeleteDir(dir): - for name in os.listdir(dir): - file = os.path.join(dir, name) - if not os.path.islink(file) and os.path.isdir(file): - DeleteDir(file) - else: - os.remove(file) - os.rmdir(dir) - -# @@PLEAC@@_9.9 -# Renaming Files - -# code sample one to one from my perlcookbook -# looks strange to me. -import os -for fname in fnames: - newname = fname - # change the file's name - try: - os.rename(fname, newname) - except OSError, err: - print "Couldn't rename %s to %s: %s!" % \ - (fname, newfile, err) - -# use os.renames if newname needs directory creation. - -#A vaguely Pythonic solution is: -import glob -def rename(files, transfunc) - for fname in fnames: - newname = transfunc(fname) - try: - os.rename(fname, newname) - except OSError, err: - print "Couldn't rename %s to %s: %s!" % \ - (fname, newfile, err) - -def transfunc(fname): - return fname[:-5] -rename(glob.glob("*.orig"), transfunc) - -def transfunc(fname): - return fname.lower() -rename([f for f in glob.glob("*") if not f.startswith("Make)], transfunc) - -def transfunc(fname): - return fname + ".bad" -rename(glob.glob("*.f"), transfunc) - -def transfunc(fname): - answer = raw_input(fname + ": ") - if answer.upper().startswith("Y"): - return fname.replace("foo", "bar") -rename(glob.glob("*"), transfunc) - -def transfunc(fname): - return ".#" + fname[:-1] -rename(glob.glob("/tmp/*~"), transfunc) - -# This _could_ be made to eval code taken directly from the command line, -# but it would be fragile -#----------------------------- - -# ^^PLEAC^^_9.10 -#----------------------------- -import os - -base = os.path.basename(path) -dirname = os.path.dirname(path) -dirname, filename = os.path.split(path) -base, ext = os.path.splitext(filename) - -#----------------------------- -path = '/usr/lib/libc.a' -filename = os.path.basename(path) -dirname = os.path.dirname(path) - -print "dir is %s, file is %s" % (dirname, filename) -# dir is /usr/lib, file is libc.a -#----------------------------- -path = '/usr/lib/libc.a' -dirname, filename = os.path.split(path) -name, ext = os.path.splitext(filename) - -print "dir is %s, name is %s, extension is %s" % (dirname, name, ext) -# NOTE: The Python code prints -# dir is /usr/lib, name is libc, extension is .a -# while the Perl code prints a '/' after the directory name -# dir is /usr/lib/, name is libc, extension is .a -#----------------------------- -import macpath -path = "Hard%20Drive:System%20Folder:README.txt" -dirname, base = macpath.split(path) -name, ext = macpath.splitext(base) - -print "dir is %s, name is %s, extension is %s" % (dirname, name, ext) -# dir is Hard%20Drive:System%20Folder, name is README, extension is .txt -#----------------------------- -# DON'T DO THIS - it's not portable. -def extension(path): - pos = path.find(".") - if pos == -1: - return "" - ext = path[pos+1:] - if "/" in ext: - # wasn't passed a basename -- this is of the form 'x.y/z' - return "" - return ext -#----------------------------- - -# @@PLEAC@@_9.11 - -#!/usr/bin/python -# sysmirror - build spectral forest of symlinks -import sys, os, os.path - -pgmname = sys.argv[0] -if len(sys.argv)!=3: - print "usage: %s realdir mirrordir" % pgmname - raise SystemExit - -(srcdir, dstdir) = sys.argv[1:3] -if not os.path.isdir(srcdir): - print "%s: %s is not a directory" % (pgmname,srcdir) - raise SystemExit -if not os.path.isdir(dstdir): - try: - os.mkdir(dstdir) - except OSError: - print "%s: can't make directory %s" % (pgmname,dstdir) - raise SystemExit - -# fix relative paths -srcdir = os.path.abspath(srcdir) -dstdir = os.path.abspath(dstdir) - -def wanted(arg, dirname, names): - for direntry in names: - relname = "%s/%s" % (dirname, direntry) - if os.path.isdir(relname): - mode = os.stat(relname).st_mode - try: - os.mkdir("%s/%s" % (dstdir,relname), mode) - except: - print "can't mkdir %s/%s" % (dstdir,relname) - raise SystemExit - else: - if relname[:2] == "./": - relname = relname[2:] - os.symlink("%s/%s" % (srcdir, relname), "%s/%s" % (dstdir,relname)) - -os.chdir(srcdir) -os.path.walk(".",wanted,None) - -# @@PLEAC@@_9.12 -# @@INCOMPLETE@@ -# @@INCOMPLETE@@ - - -# ^^PLEAC^^_10.0 -#----------------------------- -# DO NOT DO THIS... -greeted = 0 -def hello(): - global greeted - greeted += 1 - print "hi there" - -#... as using a callable object to save state is cleaner -# class hello -# def __init__(self): -# self.greeted = 0 -# def __call__(self): -# self.greeted += 1 -# print "hi there" -# hello = hello() -#----------------------------- -hello() # call subroutine hello with no arguments/parameters -#----------------------------- - -# ^^PLEAC^^_10.1 -#----------------------------- -import math -# Provided for demonstration purposes only. Use math.hypot() instead. -def hypotenuse(side1, side2): - return math.sqrt(side1**2 + side2**2) - -diag = hypotenuse(3, 4) # diag is 5.0 -#----------------------------- -print hypotenuse(3, 4) # prints 5.0 - -a = (3, 4) -print hypotenuse(*a) # prints 5.0 -#----------------------------- -both = men + women -#----------------------------- -nums = [1.4, 3.5, 6.7] -# Provided for demonstration purposes only. Use: -# ints = [int(num) for num in nums] -def int_all(nums): - retlist = [] # make new list for return - for n in nums: - retlist.append(int(n)) - return retlist -ints = int_all(nums) # nums unchanged -#----------------------------- -nums = [1.4, 3.5, 6.7] - -def trunc_em(nums): - for i,elem in enumerate(nums): - nums[i] = int(elem) -trunc_em(nums) # nums now [1,3,6] - -#----------------------------- -# By convention, if a method (or function) modifies an object -# in-place, it returns None rather than the modified object. -# None of Python's built-in functions modify in-place; methods -# such as list.sort() are somewhat more common. -mylist = [3,2,1] -mylist = mylist.sort() # incorrect - returns None -mylist = sorted(mylist) # correct - returns sorted copy -mylist.sort() # correct - sorts in-place -#----------------------------- - -# ^^PLEAC^^_10.2 -#----------------------------- -# Using global variables is discouraged - by default variables -# are visible only at and below the scope at which they are declared. -# Global variables modified by a function or method must be declared -# using the "global" keyword if they are modified -def somefunc(): - variable = something # variable is invisible outside of somefunc -#----------------------------- -import sys -name, age = sys.args[1:] # assumes two and only two command line parameters -start = fetch_time() -#----------------------------- -a, b = pair -c = fetch_time() - -def check_x(x): - y = "whatever" - run_check() - if condition: - print "got", x -#----------------------------- -def save_list(*args): - Global_List.extend(args) -#----------------------------- - -# ^^PLEAC^^_10.3 -#----------------------------- -## Python allows static nesting of scopes for reading but not writing, -## preferring to use objects. The closest equivalent to: -#{ -# my $counter; -# sub next_counter { return ++$counter } -#} -## is: -def next_counter(counter=[0]): # default lists are created once only. - counter[0] += 1 - return counter[0] - -# As that's a little tricksy (and can't make more than one counter), -# many Pythonistas would prefer either: -def make_counter(): - counter = 0 - while True: - counter += 1 - yield counter -next_counter = make_counter().next - -# Or: -class Counter: - def __init__(self): - self.counter = 0 - def __call__(self): - self.counter += 1 - return self.counter -next_counter = Counter() - -#----------------------------- -## A close equivalent of -#BEGIN { -# my $counter = 42; -# sub next_counter { return ++$counter } -# sub prev_counter { return --$counter } -#} -## is to use a list (to save the counter) and closured functions: -def make_counter(start=0): - counter = [start] - def next_counter(): - counter[0] += 1 - return counter[0] - def prev_counter(): - counter[0] -= 1 - return counter[0] - return next_counter, prev_counter -next_counter, prev_counter = make_counter() - -## A clearer way uses a class: -class Counter: - def __init__(self, start=0): - self.value = start - def next(self): - self.value += 1 - return self.value - def prev(self): - self.value -= 1 - return self.value - def __int__(self): - return self.value - -counter = Counter(42) -next_counter = counter.next -prev_counter = counter.prev -#----------------------------- - -# ^^PLEAC^^_10.4 -## This sort of code inspection is liable to change as -## Python evolves. There may be cleaner ways to do this. -## This also may not work for code called from functions -## written in C. -#----------------------------- -import sys -this_function = sys._getframe(0).f_code.co_name -#----------------------------- -i = 0 # how far up the call stack to look -module = sys._getframe(i).f_globals["__name__"] -filename = sys._getframe(i).f_code.co_filename -line = sys._getframe(i).f_lineno -subr = sys._getframe(i).f_code.co_name -has_args = bool(sys._getframe(i+1).f_code.co_argcount) - -# 'wantarray' is Perl specific - -#----------------------------- -me = whoami() -him = whowasi() - -def whoami(): - sys._getframe(1).f_code.co_name -def whowasi(): - sys._getframe(2).f_code.co_name -#----------------------------- - -# ^^PLEAC^^_10.5 -#----------------------------- -# Every variable name is a reference to an object, thus nothing special -# needs to be done to pass a list or a dict as a parameter. -list_diff(list1, list2) -#----------------------------- -# Note: if one parameter to zip() is longer it will be truncated -def add_vecpair(x, y): - return [x1+y1 for x1, y1 in zip(x, y)] - -a = [1, 2] -b = [5, 8] -print " ".join([str(n) for n in add_vecpair(a, b)]) -#=> 6 10 -#----------------------------- -# DO NOT DO THIS: -assert isinstance(x, type([])) and isinstance(y, type([])), \ - "usage: add_vecpair(list1, list2)" -#----------------------------- - -# ^^PLEAC^^_10.6 -#----------------------------- -# perl return context is not something standard in python... -# but still you can achieve something alike if you really need it -# (but you must really need it badly since you should never use this!!) -# -# see http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/284742 for more -# -# NB: it has been tested under Python 2.3.x and no guarantees can be given -# that it works under any future Python version. -import inspect,dis - -def expecting(): - """Return how many values the caller is expecting""" - f = inspect.currentframe().f_back.f_back - bytecode = f.f_code.co_code - i = f.f_lasti - instruction = ord(bytecode[i+3]) - if instruction == dis.opmap['UNPACK_SEQUENCE']: - howmany = ord(bytecode[i+4]) - return howmany - elif instruction == dis.opmap['POP_TOP']: - return 0 - return 1 - -def cleverfunc(): - howmany = expecting() - if howmany == 0: - print "return value discarded" - if howmany == 2: - return 1,2 - elif howmany == 3: - return 1,2,3 - return 1 - -cleverfunc() -x = cleverfunc() -print x -x,y = cleverfunc() -print x,y -x,y,z = cleverfunc() -print x,y,z - -# ^^PLEAC^^_10.7 -#----------------------------- -thefunc(increment= "20s", start="+5m", finish="+30m") -thefunc(start= "+5m",finish="+30m") -thefunc(finish= "+30m") -thefunc(start="+5m", increment="15s") -#----------------------------- -def thefunc(increment='10s', - finish='0', - start='0'): - if increment.endswith("m"): - pass -#----------------------------- - -# ^^PLEAC^^_10.8 -#----------------------------- -a, _, c = func() # Use _ as a placeholder... -a, ignore, c = func() # ...or assign to an otherwise unused variable -#----------------------------- - -# ^^PLEAC^^_10.9 -#----------------------------- -def somefunc(): - mylist = [] - mydict = {} - # ... - return mylist, mydict - -mylist, mydict = somefunc() -#----------------------------- -def fn(): - return a, b, c - -#----------------------------- -h0, h1, h2 = fn() -tuple_of_dicts = fn() # eg: tuple_of_dicts[2]["keystring"] -r0, r1, r2 = fn() # eg: r2["keystring"] - -#----------------------------- - -# ^^PLEAC^^_10.10 -#----------------------------- -# Note: Exceptions are almost always preferred to error values -return -#----------------------------- -def empty_retval(): - return None - -def empty_retval(): - return # identical to return None - -def empty_retval(): - pass # None returned by default (empty func needs pass) -#----------------------------- -a = yourfunc() -if a: - pass -#----------------------------- -a = sfunc() -if not a: - raise AssertionError("sfunc failed") - -assert sfunc(), "sfunc failed" -#----------------------------- - -# ^^PLEAC^^_10.11 -# Prototypes are inapplicable to Python as Python disallows calling -# functions without using brackets, and user functions are able to -# mimic built-in functions with no special actions required as they -# only flatten lists (and convert dicts to named arguments) if -# explicitly told to do so. Python functions use named parameters -# rather than shifting arguments: - -def myfunc(a, b, c=4): - print a, b, c - -mylist = [1,2] - -mydict1 = {"b": 2, "c": 3} -mydict2 = {"b": 2} - -myfunc(1,2,3) -#=> 1 2 3 - -myfunc(1,2) -#=> 1 2 4 - -myfunc(*mylist) -#=> 1 2 4 - -myfunc(5, *mylist) -#=> 5, 1, 2 - -myfunc(5, **mydict1) -#=> 5, 2, 3 - -myfunc(5, **mydict2) -#=> 5, 2, 4 - -myfunc(c=3, b=2, a=1) -#=> 1, 2, 3 - -myfunc(b=2, a=1) -#=> 1, 2, 4 - -myfunc(mylist, mydict1) -#=> [1, 2] {'c': 3, 'b': 2} 4 - -# For demonstration purposes only - don't do this -def mypush(mylist, *vals): - mylist.extend(vals) - -mylist = [] -mypush(mylist, 1, 2, 3, 4, 5) -print mylist -#=> [1, 2, 3, 4, 5] - -# ^^PLEAC^^_10.12 -#----------------------------- -raise ValueError("some message") # specific exception class -raise Exception("use me rarely") # general exception -raise "don't use me" # string exception (deprecated) -#----------------------------- -# Note that bare excepts are considered bad style. Normally you should -# trap specific exceptions. For instance these bare excepts will -# catch KeyboardInterrupt, SystemExit, and MemoryError as well as -# more common errors. In addition they force you to import sys to -# get the error message. -import warnings, sys -try: - func() -except: - warnings.warn("func raised an exception: " + str(sys.exc_info()[1])) -#----------------------------- -try: - func() -except: - warnings.warn("func blew up: " + str(sys.exc_info()[1])) -#----------------------------- -class MoonPhaseError(Exception): - def __init__(self, phase): - self.phase = phase -class FullMoonError(MoonPhaseError): - def __init__(self): - MoonPhaseError.__init__("full moon") - -def func(): - raise FullMoonError() - -# Ignore only FullMoonError exceptions -try: - func() -except FullMoonError: - pass -#----------------------------- -# Ignore only MoonPhaseError for a full moon -try: - func() -except MoonPhaseError, err: - if err.phase != "full moon": - raise -#----------------------------- - -# ^^PLEAC^^_10.13 -# There is no direct equivalent to 'local' in Python, and -# it's impossible to write your own. But then again, even in -# Perl it's considered poor style. - -# DON'T DO THIS (You probably shouldn't use global variables anyway): -class Local(object): - def __init__(self, globalname, val): - self.globalname = globalname - self.globalval = globals()[globalname] - globals()[globalname] = val - - def __del__(self): - globals()[self.globalname] = self.globalval - -foo = 4 - -def blah(): - print foo - -def blech(): - temp = Local("foo", 6) - blah() - -blah() -blech() -blah() - -#----------------------------- - -# ^^PLEAC^^_10.14 -#----------------------------- -grow = expand -grow() # calls expand() - -#----------------------------- -one.var = two.table # make one.var the same as two.table -one.big = two.small # make one.big the same as two.small -#----------------------------- -fred = barney # alias fred to barney -#----------------------------- -s = red("careful here") -print s -#> <FONT COLOR='red'>careful here</FONT> -#----------------------------- -# Note: the 'text' should be HTML escaped if it can contain -# any of the characters '<', '>' or '&' -def red(text): - return "<FONT COLOR='red'>" + text + "</FONT>" -#----------------------------- -def color_font(color, text): - return "<FONT COLOR='%s'>%s</FONT>" % (color, text) - -def red(text): return color_font("red", text) -def green(text): return color_font("green", text) -def blue(text): return color_font("blue", text) -def purple(text): return color_font("purple", text) -# etc -#----------------------------- -# This is done in Python by making an object, instead of -# saving state in a local anonymous context. -class ColorFont: - def __init__(self, color): - self.color = color - def __call__(self, text): - return "<FONT COLOR='%s'>%s</FONT>" % (self.color, text) - -colors = "red blue green yellow orange purple violet".split(" ") -for name in colors: - globals()[name] = ColorFont(name) -#----------------------------- -# If you really don't want to make a new class, you can -# fake it somewhat by passing in default args. -colors = "red blue green yellow orange purple violet".split(" ") -for name in colors: - def temp(text, color = name): - return "<FONT COLOR='%s'>%s</FONT>" % (color, text) - globals()[name] = temp - -#----------------------------- - -# ^^PLEAC^^_10.15 - -# Python has the ability to derive from ModuleType and add -# new __getattr__ and __setattr__ methods. I don't know the -# expected way to use them to emulate Perl's AUTOLOAD. Instead, -# here's how something similar would be done in Python. This -# uses the ColorFont defined above. - -#----------------------------- -class AnyColor: - def __getattr__(self, name): - return ColorFont(name) - -colors = AnyColor() - -print colors.chartreuse("stuff") - -#----------------------------- -## Skipping this translation because 'local' is too Perl -## specific, and there isn't enough context to figure out -## what this is supposed to do. -#{ -# local *yellow = \&violet; -# local (*red, *green) = (\&green, \&red); -# print_stuff(); -#} -#----------------------------- - -# ^^PLEAC^^_10.16 -#----------------------------- -def outer(arg1): - x = arg1 + 35 - def inner(): - return x * 19 - return x + inner() -#----------------------------- - -# ^^PLEAC^^_10.17 -#----------------------------- -import mailbox, sys -mbox = mailbox.PortableUnixMailbox(sys.stdin) - -def extract_data(msg, idx): - subject = msg.getheader("Subject", "").strip() - if subject[:3].lower() == "re:": - subject = subject[3:].lstrip() - text = msg.fp.read() - return subject, idx, msg, text -messages = [extract_data(idx, msg) for idx, msg in enumerate(mbox)] - -#----------------------------- -# Sorts by subject then by original position in the list -for subject, pos, msg, text in sorted(messages): - print "%s\n%s"%(msg, text) - -#----------------------------- -# Sorts by subject then date then original position -def subject_date_position(elem): - return (elem[0], elem[2].getdate("Date"), elem[1]) -messages.sort(key=subject_date_position) - -# Pre 2.4: -messages = sorted(messages, key=subject_date_position) -#----------------------------- - -# @@PLEAC@@_11.0 -#Introduction. -# In Python, all names are references. -# All objects are inherently anonymous, they don't know what names refer to them. -print ref # prints the value that the name ref refers to. -ref = 3 # assigns the name ref to the value 3. -#----------------------------- -aref = mylist -#----------------------------- -aref = [3, 4, 5] # aref is a name for this list -href = {"How": "Now", "Brown": "Cow"} # href is a name for this dictionary -#----------------------------- -# Python doesn't have autovivification as (for simple types) there is no difference between a name and a reference. -# If we try the equivalent of the Perl code we get the list, not a reference to the list. -#----------------------------- -# To handle multidimensional arrays, you should use an extension to Python, -# such as numarray (http://www.stsci.edu/resources/software_hardware/numarray) -#----------------------------- -# In Python, assignment doesn't return anything. -#----------------------------- -Nat = { "Name": "Leonhard Euler", - "Address": "1729 Ramanujan Lane\nMathworld, PI 31416", - "Birthday": 0x5bb5580 -} -#----------------------------- - -# @@PLEAC@@_11.1 -aref = mylist -anon_list = [1, 3, 5, 7, 9] -anon_copy = anon_list -implicit_creation = [2, 4, 6, 8, 10] -#----------------------------- -anon_list.append(11) -#----------------------------- -two = implicit_creation[0] -#----------------------------- -# To get the last index of a list, you can use len() -# [or list.__len__() - but don't] directly -last_idx = len(aref) - 1 - -# Normally, though, you'd use an index of -1 for the last -# element, -2 for the second last, etc. -print implicit_creation[-1] -#=> 10 - -num_items = len(aref) -#----------------------------- -last_idx = aref.__len__() - 1 -num_items = aref.__len__() -#----------------------------- -if not isinstance(someVar, type([])): - print "Expected a list" -#----------------------------- -print list_ref -#----------------------------- -# sort is in place. -list_ref.sort() -#----------------------------- -list_ref.append(item) -#----------------------------- -def list_ref(): - return [] - -aref1 = list_ref() -aref2 = list_ref() -# aref1 and aref2 point to different lists. -#----------------------------- -list_ref[N] # refers to the Nth item in the list_ref list. -#----------------------------- -# The following two statements are equivalent and return up to 3 elements -# at indices 3, 4, and 5 (if they exist). -pie[3:6] -pie[3:6:1] -#----------------------------- -# This will insert 3 elements, overwriting elements at indices 3,4, or 5 - if they exist. -pie[3:6] = ["blackberry", "blueberry", "pumpkin"] -#----------------------------- -for item in pie: - print item - -# DON'T DO THIS (this type of indexing should be done with enumerate) -# xrange does not create a list 0..len(pie) - 1, it creates an object -# that returns one index at a time. -for idx in xrange(len(pie)): - print pie[idx] - -# @@PLEAC@@_11.2 -# Making Hashes of Arrays - -hash["KEYNAME"].append("new value") - -for mystr in hash.keys(): - print "%s: %s" % (mystr, hash[mystr]) - -hash["a key"] = [3, 4, 5] - -values = hash["a key"] - -hash["a key"].append(value) - -# autovivification also does not work in python. -residents = phone2name[number] -# do this instead -residents = phone2name.get(number, []) - - -# @@PLEAC@@_11.3 -# Taking References to Hashes - -href = hash -anon_hash = { "key1":"value1", "key2" : "value2 ..." } -anon_hash_copy = anon_hash.copy() - -hash = href -value = href[key] -slice = [href[k] for k in (key1, key2, key3)] -keys = hash.keys() - -import types -if type(someref) != types.DictType: - raise "Expected a dictionary, not %s" % type(someref) -if isinstance(someref,dict): - raise "Expected a dictionary, not %s" % type(someref) - -for href in ( ENV, INC ): - for key in href.keys(): - print "%s => %s" % (key, href[key]) - -values = [hash_ref[k] for k in (key1, key2, key3)] - -for key in ("key1", "key2", "key3"): - hash_ref[k] += 7 # not like in perl but the same result. -#----------------------------- - -# @@PLEAC@@_11.4 -#----------------------------- -cref = func -cref = lambda a, b: ... -#----------------------------- -returned = cref(arguments) -#----------------------------- -funcname = "thefunc" -locals()[funcname](); -#----------------------------- -commands = { - 'happy': joy, - 'sad': sullen, - 'done': (lambda : sys.exit()), # In this case "done: sys.exit" would suffice - 'mad': angry, - } - -print "How are you?", -cmd = raw_input() -if cmd in commands: - commands[cmd]() -else: - print "No such command: %s" % cmd -#----------------------------- -def counter_maker(): - start = [0] - def counter_function(): - # start refers to the variable defined in counter_maker, but - # we can't reassign or increment variables in parent scopes. - # By using a one-element list we can modify the list without - # reassigning the variable. This way of using a list is very - # like a reference. - start[0] += 1 - return start[0]-1 - return counter_function - -counter = counter_maker() -for i in range(5): - print counter() -#----------------------------- -counter1 = counter_maker() -counter2 = counter_maker() - -for i in range(5): - print counter1() -print counter1(), counter2() -#=> 0 -#=> 1 -#=> 2 -#=> 3 -#=> 4 -#=> 5 0 -#----------------------------- -import time -def timestamp(): - start_time = time.time() - def elapsed(): - return time.time() - start_time - return elapsed -early = timestamp() -time.sleep(20) -later = timestamp() -time.sleep(10) -print "It's been %d seconds since early" % early() -print "It's been %d seconds since later" % later() -#=> It's been 30 seconds since early. -#=> It's been 10 seconds since later. -#----------------------------- - -# @@PLEAC@@_11.5 -# A name is a reference to an object and an object can be referred to -# by any number of names. There is no way to manipulate pointers or -# an object's id. This section is thus inapplicable. -x = 1 -y = x -print x, id(x), y, id(y) -x += 1 # "x" now refers to a different object than y -print x, id(x), y, id(y) -y = 4 # "y" now refers to a different object than it did before -print x, id(x), y, id(y) - -# Some objects (including ints and strings) are immutable, however, which -# can give the illusion of a by-value/by-reference distinction: -a = x = [1] -b = y = 1 -c = z = "s" -print a, b, c -#=> [1] 1 s - -x += x # calls list.__iadd__ which is inplace. -y += y # can't find int.__iadd__ so calls int.__add__ which isn't inplace -z += z # can't find str.__iadd__ so calls str.__add__ which isn't inplace -print a, b, c -#=> [1, 1] 1 s - -# @@PLEAC@@_11.6 -# As indicated by the previous section, everything is referenced, so -# just create a list as normal, and beware that augmented assignment -# works differently with immutable objects to mutable ones: -mylist = [1, "s", [1]] -print mylist -#=> [1, s, [1]] - -for elem in mylist: - elem *= 2 -print mylist -#=> [1, s, [1, 1]] - -mylist[0] *= 2 -mylist[-1] *= 2 -print mylist -#=> [1, s, [1, 1, 1, 1]] - -# If you need to modify every value in a list, you should use a list comprehension -# which does NOT modify inplace: -import math -mylist = [(val**3 * 4/3*math.pi) for val in mylist] - -# @@PLEAC@@_11.7 -#----------------------------- -c1 = mkcounter(20) -c2 = mkcounter(77) - -print "next c1: %d" % c1['next']() # 21 -print "next c2: %d" % c2['next']() # 78 -print "next c1: %d" % c1['next']() # 22 -print "last c1: %d" % c1['prev']() # 21 -print "old c2: %d" % c2['reset']() # 77 -#----------------------------- -# DON'T DO THIS. Use an object instead -def mkcounter(start): - count = [start] - def next(): - count[0] += 1 - return count[0] - def prev(): - count[0] -= 1 - return count[0] - def get(): - return count[0] - def set(value): - count[0] = value - return count[0] - def bump(incr): - count[0] += incr - return count[0] - def reset(): - count[0] = start - return count[0] - return { - 'next': next, 'prev': prev, 'get': get, 'set': set, - 'bump': bump, 'reset': reset, 'last': prev} -#----------------------------- - -# @@PLEAC@@_11.8 -#----------------------------- -mref = obj.meth -# later... -mref("args", "go", "here") -#----------------------------- - -# @@PLEAC@@_11.9 -#----------------------------- -record = { - "name": "Jason", - "empno": 132, - "title": "deputy peon", - "age": 23, - "salary": 37000, - "pals": ["Norbert", "Rhys", "Phineas"], -} -print "I am %s, and my pals are %s." % (record["name"], - ", ".join(record["pals"])) -#----------------------------- -byname = {} -byname[record["name"]] = record - -rp = byname.get("Aron") -if rp: - print "Aron is employee %d."% rp["empno"] - -byname["Jason"]["pals"].append("Theodore") -print "Jason now has %d pals." % len(byname["Jason"]["pals"]) - -for name, record in byname.items(): - print "%s is employee number %d." % (name, record["empno"]) - -employees = {} -employees[record["empno"]] = record; - -# lookup by id -rp = employees.get(132) -if (rp): - print "Employee number 132 is %s." % rp["name"] - -byname["Jason"]["salary"] *= 1.035 - -peons = [r for r in employees.values() if r["title"] == "peon"] -tsevens = [r for r in employees.values() if r["age"] == 27] - -# Go through all records -print employees.values() - -for rp in sorted(employees.values(), key=lambda x:x["age"]): - print "%s is age %d."%(rp["name"], rp["age"]) - -# use @byage, an array of arrays of records -byage = {} -byage[record["age"]] = byage.get(record["age"], []) + [record] - -for age, records in byage.items(): - print records - print "Age %s:"%age, - for rp in records: - print rp["name"], - print -#----------------------------- - -# @@PLEAC@@_11.10 -#----------------------------- -FieldName: Value -#----------------------------- -for record in list_of_records: - # Note: sorted added in Python 2.4 - for key in sorted(record.keys()): - print "%s: %s" % (key, record[key]) - print -#----------------------------- -import re -list_of_records = [{}] -while True: - line = sys.stdin.readline() - if not line: - # EOF - break - # Remove trailing \n: - line = line[:1] - if not line.strip(): - # New record - list_of_records.append({}) - continue - key, value = re.split(r':\s*', line, 1) - # Assign the key/value to the last item in the list_of_records: - list_of_records[-1][key] = value -#----------------------------- -# @@PLEAC@@_11.11 -import pprint - -mylist = [[1,2,3], [4, [5,6,7], 8,9, [0,3,5]], 7, 8] -mydict = {"abc": "def", "ghi":[1,2,3]} -pprint.pprint(mylist, width=1) - -fmtdict = pprint.pformat(mydict, width=1) -print fmtdict -# "import pprint; help(pprint)" for more details - -# @@INCOMPLETE@@ -# Note that pprint does not currently handle user objects - -#----------------------------- -# @@PLEAC@@_11.12 -newlist = list(mylist) # shallow copy -newdict = dict(mydict) # shallow copy - -# Pre 2.3: -import copy -newlist = copy.copy(mylist) # shallow copy -newdict = copy.copy(mydict) # shallow copy - -# shallow copies copy a data structure, but don't copy the items in those -# data structures so if there are nested data structures, both copy and -# original will refer to the same object -mylist = ["1", "2", "3"] -newlist = list(mylist) -mylist[0] = "0" -print mylist, newlist -#=> ['0', '2', '3'] ['1', '2', '3'] - -mylist = [["1", "2", "3"], 4] -newlist = list(mylist) -mylist[0][0] = "0" -print mylist, newlist -#=> [['0', '2', '3'], 4] [['0', '2', '3'], 4] -#----------------------------- -import copy -newlist = copy.deepcopy(mylist) # deep copy -newdict = copy.deepcopy(mydict) # deep copy - -# deep copies copy a data structure recursively: -import copy - -mylist = [["1", "2", "3"], 4] -newlist = copy.deepcopy(mylist) -mylist[0][0] = "0" -print mylist, newlist -#=> [['0', '2', '3'], 4] [['1', '2', '3'], 4] -#----------------------------- -# @@PLEAC@@_11.13 -import pickle -class Foo(object): - def __init__(self): - self.val = 1 - -x = Foo() -x.val = 3 -p_x = pickle.dumps(x) # Also pickle.dump(x, myfile) which writes to myfile -del x -x = pickle.loads(p_x) # Also x = pickle.load(myfile) which loads from myfile -print x.val -#=> 3 -#----------------------------- -# @@PLEAC@@_11.14 -import os, shelve -fname = "testfile.db" -if not os.path.exists(fname): - d = shelve.open("testfile.db") - for i in range(100000): - d[str(i)] = i - d.close() - -d = shelve.open("testfile.db") -print d["100"] -print d["1212010201"] # KeyError -#----------------------------- - -# @@PLEAC@@_11.15 -# bintree - binary tree demo program -# Use the heapq module instead? -import random -import warnings - -class BTree(object): - def __init__(self): - self.value = None - - ### insert given value into proper point of - ### the tree, extending this node if necessary. - def insert(self, value): - if self.value is None: - self.left = BTree() - self.right = BTree() - self.value = value - elif self.value > value: - self.left.insert(value) - elif self.value < value: - self.right.insert(value) - else: - warnings.warn("Duplicate insertion of %s."%value) - - # recurse on left child, - # then show current value, - # then recurse on right child. - def in_order(self): - if self.value is not None: - self.left.in_order() - print self.value, - self.right.in_order() - - # show current value, - # then recurse on left child, - # then recurse on right child. - def pre_order(self): - if self.value is not None: - print self.value, - self.left.pre_order() - self.right.pre_order() - - # recurse on left child, - # then recurse on right child, - # then show current value. - def post_order(self): - if self.value is not None: - self.left.post_order() - self.right.post_order() - print self.value, - - # find out whether provided value is in the tree. - # if so, return the node at which the value was found. - # cut down search time by only looking in the correct - # branch, based on current value. - def search(self, value): - if self.value is not None: - if self.value == value: - return self - if value < self.value: - return self.left.search(value) - else: - return self.right.search(value) - -def test(): - root = BTree() - - for i in range(20): - root.insert(random.randint(1, 1000)) - - # now dump out the tree all three ways - print "Pre order: ", root.pre_order() - print "In order: ", root.in_order() - print "Post order:", root.post_order() - - ### prompt until empty line - while True: - val = raw_input("Search? ").strip() - if not val: - break - val = int(val) - found = root.search(val) - if found: - print "Found %s at %s, %s"%(val, found, found.value) - else: - print "No %s in tree" % val - -if __name__ == "__main__": - test() - - -# ^^PLEAC^^_12.0 -#----------------------------- -## Python's "module" is the closest equivalent to Perl's "package" - - -#=== In the file "Alpha.py" -name = "first" - -#=== End of file - -#=== In the file "Omega.py" - -name = "last" -#=== End of file - -import Alpha, Omega -print "Alpha is %s, Omega is %s." % (Alpha.name, Omega.name) -#> Alpha is first, Omega is last. -#----------------------------- -# Python does not have an equivalent to "compile-time load" -import sys - -# Depending on the implementation, this could use a builtin -# module or load a file with the extension .py, .pyc, pyo, .pyd, -# .so, .dll, or (with imputils) load from other files. -import Cards.Poker - -#----------------------------- -#=== In the file Cards/Poker.py -__all__ = ["card_deck", "shuffle"] # not usually needed -card_deck = [] -def shuffle(): - pass - -#----------------------------- - -# ^^PLEAC^^_12.1 -#----------------------------- -#== In the file "YourModule.py" - -__version__ = (1, 0) # Or higher -__all__ = ["...", "..."] # Override names included in "... import *" - # Note: 'import *' is considered poor style - # and it is rare to use this variable. -######################## -# your code goes here -######################## - -#----------------------------- -import YourModule # Import the module into my package - # (does not import any of its symbols) - -import YourModule as Module # Use a different name for the module - -from YourModule import * # Import all module symbols not starting - # with an underscore (default); if __all__ - # is defined, only imports those symbols. - # Using this is discouraged unless the - # module is specifically designed for it. - -from YourModule import name1, name2, xxx - # Import the named symbols from the module - -from YourModule import name1 as name2 - # Import the named object, but use a - # different name to access it locally. - -#----------------------------- -__all__ = ["F1", "F2", "List"] -#----------------------------- -__all__ = ["Op_Func", "Table"] -#----------------------------- -from YourModule import Op_Func, Table, F1 -#----------------------------- -from YourModule import Functions, Table -#----------------------------- - -# ^^PLEAC^^_12.2 -#----------------------------- -# no import -mod = "module" -try: - __import__(mod) -except ImportError, err: - raise ImportError("couldn't load %s: %s" % (mod, err)) - -# imports into current package -try: - import module -except ImportError, err: - raise ImportError("couldn't load 'module': %s" % (err, )) - -# imports into current package, if the name is known -try: - import module -except ImportError, err: - raise ImportError("couldn't load 'module': %s" % (err, )) - -# Use a fixed local name for a named module -mod = "module" -try: - local_name = __import__(mod) -except ImportError, err: - raise ImportError("couldn't load %s: %s" % (mod, err)) - -# Use the given name for the named module. -# (You probably don't need to do this.) -mod = "module" -try: - globals()[mod] = __import__(mod) -except ImportError, err: - raise ImportError("couldn't load %s: %s" % (mod, err)) - -#----------------------------- -DBs = "Giant.Eenie Giant.Meanie Mouse.Mynie Moe".split() -for mod in DBs.split(): - try: - loaded_module = __import__(mod) - except ImportError: - continue - # __import__ returns a reference to the top-most module - # Need to get the actual submodule requested. - for term in mod.split(".")[:-1]: - loaded_module = getattr(loaded_module, term) - break -else: - raise ImportError("None of %s loaded" % DBs) -#----------------------------- - -# ^^PLEAC^^_12.3 -#----------------------------- -import sys -if __name__ == "__main__": - if len(sys.argv) != 3 or not sys.argv[1].isdigit() \ - or not sys.argv[2].isdigit(): - raise SystemExit("usage: %s num1 num2" % sys.argv[0]) - -import Some.Module -import More.Modules -#----------------------------- -if opt_b: - import math -#----------------------------- -from os import O_EXCL, O_CREAT, O_RDWR - -#----------------------------- -import os -O_EXCL = os.O_EXCL -O_CREAT = os.O_CREAT -O_RDWR = os.O_RDWR -#----------------------------- -import os -O_EXCL, O_CREAT, O_RDWR = os.O_EXCL, os.O_CREAT, os.O_RDWR -#----------------------------- -load_module('os', "O_EXCL O_CREAT O_RDWR".split()) - -def load_module(module_name, symbols): - module = __import__(module_name) - for symbol in symbols: - globals()[symbol] = getattr(module, symbol) -#----------------------------- - -# ^^PLEAC^^_12.4 -#----------------------------- -# Python doesn't have Perl-style packages - -# Flipper.py -__version__ = (1, 0) - -__all__ = ["flip_boundary", "flip_words"] - -Separatrix = ' ' # default to blank - -def flip_boundary(sep = None): - prev_sep = Separatrix - if sep is not None: - global Separatrix - Separatrix = sep - return prev_sep - -def flip_words(line): - words = line.split(Separatrix) - words.reverse() - return Separatrix.join(words) -#----------------------------- - -# ^^PLEAC^^_12.5 -#----------------------------- -this_pack = __name__ -#----------------------------- -that_pack = sys._getframe(1).f_globals.get("__name__", "<string>") -#----------------------------- -print "I am in package", __name__ -#----------------------------- -def nreadline(count, myfile): - if count <= 0: - raise ValueError("Count must be > 0") - return [myfile.readline() for i in range(count)] - -def main(): - myfile = open("/etc/termcap") - a, b, c = nreadline(3, myfile) - myfile.close() - -if __name__ == "__main__": - main() - -# DON'T DO THIS: -import sys - -def nreadline(count, handle_name): - assert count > 0, "count must be > 0" - locals = sys._getframe(1).f_locals - if not locals.has_key(handle_name): - raise AssertionError("need open filehandle") - infile = locals[handle_name] - retlist = [] - for line in infile: - retlist.append(line) - count -= 1 - if count == 0: - break - return retlist - -def main(): - FH = open("/etc/termcap") - a, b, c = nreadline(3, "FH") - -if __name__ == "__main__": - main() -#----------------------------- - -# ^^PLEAC^^_12.6 -#----------------------------- -## There is no direct equivalent in Python to an END block -import time, os, sys - -# Tricks to ensure the needed functions exist during module cleanup -def _getgmtime(asctime=time.asctime, gmtime=time.gmtime, - t=time.time): - return asctime(gmtime(t())) - -class Logfile: - def __init__(self, file): - self.file = file - - def _logmsg(self, msg, argv0=sys.argv[0], pid=os.getpid(), - _getgmtime=_getgmtime): - # more tricks to keep all needed references - now = _getgmtime() - print>>self.file, argv0, pid, now + ":", msg - - def logmsg(self, msg): - self._logmsg(self.file, msg) - - def __del__(self): - self._logmsg("shutdown") - self.file.close() - - def __getattr__(self, attr): - # forward everything else to the file handle - return getattr(self.file, attr) - -# 0 means unbuffered -LF = Logfile(open("/tmp/mylog", "a+", 0)) -logmsg = LF.logmsg - -#----------------------------- -## It is more appropriate to use try/finally around the -## main code, so the order of initialization and finalization -## can be specified. -if __name__ == "__main__": - import logger - logger.init("/tmp/mylog") - try: - main() - finally: - logger.close() - -#----------------------------- - -# ^^PLEAC^^_12.7 -#----------------------------- -#% python -c 'import sys\ -for i, name in zip(xrange(sys.maxint), sys.path):\ - print i, repr(name) -#> 0 '' -#> 1 '/usr/lib/python2.2' -#> 2 '/usr/lib/python2.2/plat-linux2' -#> 3 '/usr/lib/python2.2/lib-tk' -#----------------------------- -# syntax for sh, bash, ksh, or zsh -#$ export PYTHONPATH=$HOME/pythonlib - -# syntax for csh or tcsh -#% setenv PYTHONPATH ~/pythonlib -#----------------------------- -import sys -sys.path.insert(0, "/projects/spectre/lib") -#----------------------------- -import FindBin -sys.path.insert(0, FindBin.Bin) -#----------------------------- -import FindBin -Bin = "Name" -bin = getattr(FindBin, Bin) -sys.path.insert(0, bin + "/../lib") -#----------------------------- - -# ^^PLEAC^^_12.8 -#----------------------------- -#% h2xs -XA -n Planets -#% h2xs -XA -n Astronomy::Orbits -#----------------------------- -# @@INCOMPLETE@@ -# @@INCOMPLETE@@ -# Need a distutils example -#----------------------------- - -# ^^PLEAC^^_12.9 -#----------------------------- -# Python compiles a file to bytecode the first time it is imported and -# stores this compiled form in a .pyc file. There is thus less need for -# incremental compilation as once there is a .pyc file, the sourcecode -# is only recompiled if it is modified. - -# ^^PLEAC^^_12.10 -#----------------------------- -# See previous section - -# ^^PLEAC^^_12.11 -#----------------------------- -## Any definition in a Python module overrides the builtin -## for that module - -#=== In MyModule -def open(): - pass # TBA -#----------------------------- -from MyModule import open -file = open() -#----------------------------- - -# ^^PLEAC^^_12.12 -#----------------------------- -def even_only(n): - if n & 1: # one way to test - raise AssertionError("%s is not even" % (n,)) - #.... - -#----------------------------- -def even_only(n): - if n % 2: # here's another - # choice of exception depends on the problem - raise TypeError("%s is not even" % (n,)) - #.... - -#----------------------------- -import warnings -def even_only(n): - if n & 1: # test whether odd number - warnings.warn("%s is not even, continuing" % (n)) - n += 1 - #.... -#----------------------------- -warnings.filterwarnings("ignore") -#----------------------------- - -# ^^PLEAC^^_12.13 -#----------------------------- -val = getattr(__import__(packname), varname) -vals = getattr(__import__(packname), aryname) -getattr(__import__(packname), funcname)("args") - -#----------------------------- -# DON'T DO THIS [Use math.log(val, base) instead] -import math -def make_log(n): - def logn(val): - return math.log(val, n) - return logn - -# Modifying the global dictionary - this could also be done -# using locals(), or someobject.__dict__ -globaldict = globals() -for i in range(2, 1000): - globaldict["log%s"%i] = make_log(i) - -# DON'T DO THIS -for i in range(2,1000): - exec "log%s = make_log(i)"%i in globals() - -print log20(400) -#=>2.0 -#----------------------------- -blue = colours.blue -someobject.blue = colours.azure # someobject could be a module... -#----------------------------- - -# ^^PLEAC^^_12.14 -#----------------------------- -# Python extension modules can be imported and used just like -# a pure python module. -# -# See http://www.cosc.canterbury.ac.nz/~greg/python/Pyrex/ for -# information on how to create extension modules in Pyrex [a -# language that's basically Python with type definitions which -# converts to compiled C code] -# -# See http://www.boost.org/libs/python/doc/ for information on how -# to create extension modules in C++. -# -# See http://www.swig.org/Doc1.3/Python.html for information on how -# to create extension modules in C/C++ -# -# See http://docs.python.org/ext/ext.html for information on how to -# create extension modules in C/C++ (manual reference count management). -# -# See http://cens.ioc.ee/projects/f2py2e/ for information on how to -# create extension modules in Fortran -# -# See http://www.scipy.org/Weave for information on how to -# include inline C code in Python code. -# -# @@INCOMPLETE@@ Need examples of FineTime extensions using the different methods... -#----------------------------- - -# ^^PLEAC^^_12.15 -#----------------------------- -# See previous section -#----------------------------- - -# ^^PLEAC^^_12.16 -#----------------------------- -# To document code, use docstrings. A docstring is a bare string that -# is placed at the beginning of a module or immediately after the -# definition line of a class, method, or function. Normally, the -# first line is a brief description of the object; if a longer -# description is needed, it commences on the third line (the second -# line being left blank). Multiline comments should use triple -# quoted strings. -# -# Docstrings are automagically assigned to an object's __doc__ property. -# -# In other words these three classes are identical: -class Foo(object): - "A class demonstrating docstrings." - -class Foo(object): - __doc__ = "A class demonstrating docstrings." - -class Foo(object): - pass -Foo.__doc__ = "A class demonstrating docstrings." - -# as are these two functions: -def foo(): - "A function demonstrating docstrings." - -def foo(): - pass -foo.__doc__ = "A function demonstrating docstrings." - -# the pydoc module is used to display a range of information about -# an object including its docstrings: -import pydoc -print pydoc.getdoc(int) -pydoc.help(int) - -# In the interactive interpreter, objects' documentation can be -# using the help function: -help(int) - -#----------------------------- - -# ^^PLEAC^^_12.17 -#----------------------------- -# Recent Python distributions are built and installed with disutils. -# -# To build and install under unix -# -# % python setup.py install -# -# If you want to build under one login and install under another -# -# % python setup.py build -# $ python setup.py install -# -# A package may also be available prebuilt, eg, as an RPM or Windows -# installer. Details will be specific to the operating system. - -#----------------------------- -# % python setup.py --prefix ~/python-lib -#----------------------------- - - -# ^^PLEAC^^_12.18 -#----------------------------- -#== File Some/Module.py - -# There are so many differences between Python and Perl that -# it isn't worthwhile trying to come up with an equivalent to -# this Perl code. The Python code is much smaller, and there's -# no need to have a template. - -#----------------------------- - -# ^^PLEAC^^_12.19 -#----------------------------- -#% pmdesc -#----------------------------- -import sys, pydoc - -def print_module_info(path, modname, desc): - # Skip files starting with "test_" - if modname.split(".")[-1].startswith("test_"): - return - try: - # This assumes the modules are safe for importing, - # in that they don't have side effects. Could also - # grep the file for the __version__ line. - mod = pydoc.safeimport(modname) - except pydoc.ErrorDuringImport: - return - version = getattr(mod, "__version__", "unknown") - if isinstance(version, type("")): - # Use the string if it's given - pass - else: - # Assume it's a list of version numbers, from major to minor - ".".join(map(str, version)) - synopsis, text = pydoc.splitdoc(desc) - print "%s (%s) - %s" % (modname, version, synopsis) - -scanner = pydoc.ModuleScanner() -scanner.run(print_module_info) - -#----------------------------- - - -# ^^PLEAC^^_13.0 -#----------------------------- -# Inside a module named 'Data' / file named 'Data.py' -class Encoder(object): - pass -#----------------------------- -obj = [3, 5] -print type(obj), id(obj), ob[1] - -## Changing the class of builtin types is not supported -## in Python. - -#----------------------------- -obj.Stomach = "Empty" # directly accessing an object's contents -obj.NAME = "Thag" # uppercase field name to make it stand out -(optional) -#----------------------------- -encoded = object.encode("data") -#----------------------------- -encoded = Data.Encoder.encode("data") -#----------------------------- -class Class(object): - def __init__(self): - pass -#----------------------------- -object = Class() -#----------------------------- -class Class(object): - def class_only_method(): - pass # more code here - class_only_method = staticmethod(class_only_method) - -#----------------------------- -class Class(object): - def instance_only_method(self): - pass # more code here -#----------------------------- -lector = Human.Cannibal() -lector.feed("Zak") -lector.move("New York") -#----------------------------- -# NOTE: it is rare to use these forms except inside of -# methods to call specific methods from a parent class -lector = Human.Cannibal() -Human.Cannibal.feed(lector, "Zak") -Human.Cannibal.move(lector, "New York") -#----------------------------- -print>>sys.stderr, "stuff here\n" - -# ^^PLEAC^^_13.1 -#----------------------------- -class Class(object): - pass -#----------------------------- -import time -class Class(object): - def __init__(self): - self.start = time.time() # init data fields - self.age = 0 -#----------------------------- -import time -class Class(object): - def __init__(self, **kwargs): - # Sets self.start to the current time, and self.age to 0. If called - # with arguments, interpret them as key+value pairs to - # initialize the object with - self.age = 0 - self.__dict__.update(kwargs) -#----------------------------- - -# ^^PLEAC^^_13.2 -#----------------------------- -import time -class Class(object): - def __del__(self): - print self, "dying at", time.ctime() -#----------------------------- -## Why is the perl code introducing a cycle? I guess it's an -## example of how to keep from calling the finalizer -self.WHATEVER = self -#----------------------------- - -# ^^PLEAC^^_13.3 -#----------------------------- -# It is standard practice to access attributes directly: -class MyClass(object) - def __init__(self): - self.name = "default" - self.age = 0 -obj = MyClass() -obj.name = "bob" -print obj.name -obj.age += 1 - -# If you later find that you need to compute an attribute, you can always -# retrofit a property(), leaving user code untouched: -class MyClass(object): - def __init__(self): - self._name = "default" - self._age = 0 - - def get_name(self): - return self._name - def set_name(self, name): - self._name = name.title() - name = property(get_name, set_name) - - def get_age(self): - return self._age - def set_age(self, val): - if val < 0: - raise ValueError("Invalid age: %s" % val) - self._age = val - age = property(get_age, set_age) -obj = MyClass() -obj.name = "bob" -print obj.name -obj.age += 1 - -# DON'T DO THIS - explicit getters and setters should not be used: -class MyClass(object): - def __init__(self): - self.name = "default" - def get_name(self): - return self.name - def set_name(self, name): - self.name = name.title() -obj = MyClass() -obj.set_name("bob") -print obj.get_name() -#----------------------------- -## DON'T DO THIS (It's complex, ugly, and unnecessary): -class MyClass(object): - def __init__(self): - self.age = 0 - def name(self, *args): - if len(args) == 0: - return self.name - elif len(args) == 1: - self.name = args[0] - else: - raise TypeError("name only takes 0 or 1 arguments") - def age(self, *args): - prev = self.age - if args: - self.age = args[0] - return prev - -# sample call of get and set: happy birthday! -obj.age(1 + obj.age()) - -#----------------------------- -him = Person() -him.NAME = "Sylvester" -him.AGE = 23 -#----------------------------- -# Here's another way to implement the 'obj.method()' is a getter -# and 'obj.method(value)' is a settor. Again, this is not a -# common Python idiom and should not be used. See below for a -# more common way to do parameter checking of attribute assignment. - -import re, sys - -def carp(s): - sys.stderr.write("WARNING: " + s + "\n") - -class Class: - no_name = [] - - def name(self, value = no_name): - if value is Class.no_name: - return self.NAME - value = self._enforce_name_value(value) - self.NAME = value - - def _enforce_name_value(self, value): - if re.search(r"[^\s\w'-]", value): - carp("funny characters in name") - if re.search(r"\d", value): - carp("numbers in name") - if not re.search(r"\S+(\s+\S+)+", value): - carp("prefer multiword name") - if not re.search(r"\S", value): - carp("name is blank") - return value.upper() # enforce capitalization -#----------------------------- -# A more typical way to enforce restrictions on a value -# to set -class Class: - def __setattr__(self, name, value): - if name == "name": - value = self._enforce_name_value(value) # Do any conversions - self.__dict__[name] = value # Do the default __setattr__ action - - def _enforce_name_value(self, value): - if re.search(r"[^\s\w'-]", value): - carp("funny characters in name") - if re.search(r"\d", value): - carp("numbers in name") - if not re.search(r"\S+(\s+\S+)+", value): - carp("prefer multiword name") - if not re.search(r"\S", value): - carp("name is blank") - return value.upper() # enforce capitalization - -#----------------------------- -class Person: - def __init__(self, name = None, age = None, peers = None): - if peers is None: peers = [] # See Python FAQ 6.25 - self.name = name - self.age = age - self.peers = peers - - def exclaim(self): - return "Hi, I'm %s, age %d, working with %s" % \ - (self.name, self.age, ", ".join(self.peers)) - - def happy_birthday(self): - self.age += 1 - return self.age -#----------------------------- - -# ^^PLEAC^^_13.4 -#----------------------------- -## In the module named 'Person' ... -def population(): - return Person.body_count[0] - -class Person(object): - body_count = [0] # class variable - shared across all instances - - def __init__(self): - self.body_count[0] += 1 - - def __del__(self): # Beware - may be non-deterministic (Jython)! - self.body_count[0] -= 1 - -# later, the user can say this: -import Person -people = [] -for i in range(10): - people.append(Person.Person()) -print "There are", Person.population(), "people alive." - -#=> There are 10 people alive. -#----------------------------- -him = Person() -him.gender = "male" - -her = Person() -her.gender = "female" - -#----------------------------- -FixedArray.max_bounds = 100 # set for whole class -alpha = FixedArray.FixedArray() -print "Bound on alpha is", alpha.max_bounds -#=>100 - -beta = FixedArray.FixedArray() -beta.max_bounds = 50 # still sets for whole class -print "Bound on alpha is", alpha.max_bounds -#=>50 -#----------------------------- -# In the module named 'FixedArray' - -class FixedArray(object): - _max_bounds = [7] # Shared across whole class - - def __init__(self, bounds=None): - if bounds is not None: - self.max_bounds = bounds - - def get_max_bounds(self): - return self._max_bounds[0] - def set_max_bounds(self, val): - self._max_bounds[0] = val - max_bounds = property(get_max_bounds, set_max_bounds) -#----------------------------- - -# ^^PLEAC^^_13.5 -#----------------------------- -# There isn't the severe separation between scalar, arrays and hashs -# in Python, so there isn't a direct equivalent to the Perl code. -class Person: - def __init__(self, name=None, age=None, peers=None): - if peers is None: - peers = [] - self.name = name - self.age = age - self.peers = peers - -p = Person("Jason Smythe", 13, ["Wilbur", "Ralph", "Fred"]) - -# or this way. (This is not the prefered style as objects should -# be constructed with all the appropriate data, if possible.) - -p = Person() # allocate an empty Person -p.name = "Jason Smythe" # set its name field -p.age = 13 # set its age field -p.peers.extend( ["Wilbur", "Ralph", "Fred" ] ) # set its peers field - -p.peers = ["Wilbur", "Ralph", "Fred"] - -p.peers[:]= ["Wilbur", "Ralph", "Fred"] - -# fetch various values, including the zeroth friend -print "At age %d, %s's first friend is %s." % \ - (p.age, p.name, p.peers[0]) -#----------------------------- -# This isn't very Pythonic - should create objects with the -# needed data, and not depend on defaults and modifing the object. -import sys -def carp(s): - sys.stderr.write("WARNING: " + s + "\n") - -class Person: - def __init__(self, name = "", age = 0): - self.name = name - self.age = age - def __setattr__(self, name, value): - if name == "age": - # This is very unpythonic - if not isinstance(value, type(0)): - carp("age '%s' isn't numeric" % (value,)) - if value > 150: carp("age '%s' is unreasonable" % (value,)) - self.__dict__[name] = value - -class Family: - def __init__(self, head = None, address = "", members = None): - if members is None: members = [] - self.head = head or Person() - self.address = address - self.members = members - -folks = Family() - -dad = folks.head -dad.name = "John" -dad.age = 34 - -print "%s's age is %d" % (folks.head.name, folks.head.age) -#----------------------------- -class Card: - def __init__(self, name=None, color=None, cost=None, - type=None, release=None, text=None): - self.name = name - self.color = color - self.cost = cost - self.type = type - self.release = release - self.type = type -#----------------------------- -# For positional args -class Card: - _names = ("name", "color", "cost", "type", "release", "type") - def __init__(self, *args): - assert len(args) <= len(self._names) - for k, v in zip(self._names, args): - setattr(self, k, None) -#----------------------------- -# For keyword args -class Card: - _names = ("name", "color", "cost", "type", "release", "type") - def __init__(self, **kwargs): - for k in self._names: # Set the defaults - setattr(self, k, None) - for k, v in kwargs.items(): # add in the kwargs - assert k in self._names, "Unexpected kwarg: " + k - setattr(self, k, v) -#----------------------------- -class hostent: - def __init__(self, addr_list = None, length = None, - addrtype = None, aliases = None, name = None): - self.addr_list = addr_list or [] - self.length = length or 0 - self.addrtype = addrtype or "" - self.aliases = aliases or [] - self.name = name or "" -#----------------------------- -## XXX What do I do with these? -#define h_type h_addrtype -#define h_addr h_addr_list[0] -#----------------------------- -# make (hostent object)->type() same as (hostent object)->addrtype() -# -# *hostent::type = \&hostent::addrtype; -# -# # make (hostenv object)-> -# addr() -# same as (hostenv object)->addr_list(0) -#sub hostent::addr { shift->addr_list(0,@_) } -#----------------------------- -# No equivalent to Net::hostent (Python uses an unnamed tuple) -#package Extra::hostent; -#use Net::hostent; -#@ISA = qw(hostent); -#sub addr { shift->addr_list(0,@_) } -#1; -#----------------------------- - -# ^^PLEAC^^_13.6 -#----------------------------- -class Class(Parent): - pass -#----------------------------- -## Note: this is unusual in Python code -ob1 = SomeClass() -# later on -ob2 = ob1.__class__() -#----------------------------- -## Note: this is unusual in Python code -ob1 = Widget() -ob2 = ob1.__class__() -#----------------------------- -# XXX I do not know the intent of the original Perl code -# Do not use this style of programming in Python. -import time -class Person(possible,base,classes): - def __init__(self, *args, **kwargs): - # Call the parents' constructors, if there are any - for baseclass in self.__class__.__bases__: - init = getattr(baseclass, "__init__") - if init is not None: - init(self, *args, **kwargs) - self.PARENT = parent # init data fields - self.START = time.time() - self.AGE = 0 -#----------------------------- - -# ^^PLEAC^^_13.7 -#----------------------------- -methname = "flicker" -getattr(obj, methname)(10) # calls obj->flicker(10); - -# call three methods on the object, by name -for m in ("start", "run", "stop"): - getattr(obj, m)() -#----------------------------- -methods = ("name", "rank", "serno") -his_info = {} -for m in methods: - his_info[m] = getattr(ob, m)() - -# same as this: - -his_info = { - 'name': ob.name(), - 'rank': ob.rank(), - 'serno': ob.serno(), -} -#----------------------------- -fnref = ob.method -#----------------------------- -fnref(10, "fred") -#----------------------------- -obj.method(10, "fred") -#----------------------------- -# XXX Not sure if this is the correct translation. -# XXX Is 'can' special? -if isinstance(obj_target, obj.__class__): - obj.can('method_name')(obj_target, *arguments) -#----------------------------- - -# ^^PLEAC^^_13.8 -#----------------------------- -isinstance(obj, mimetools.Message) -issubclass(obj.__class__, mimetools.Message) - -if hasattr(obj, "method_name"): # check method validity - pass -#----------------------------- -## Explicit type checking is needed fewer times than you think. -his_print_method = getattr(obj, "as_string", None) -#----------------------------- -__version__ = (3, 0) -Some_Module.__version__ - -# Almost never used, and doesn't work for builtin types, which don't -# have a __module__. - -his_vers = obj.__module__.__version__ -#----------------------------- -if Some_Module.__version__ < (3, 0): - raise ImportError("Some_Module version %s is too old, expected (3, 0)" % - (Some_Module.__version__,)) -# or more simply -assert Some_Module.__version__ >= (3, 0), "version too old" - -#----------------------------- -__VERSION__ = '1.01' -#----------------------------- - -# ^^PLEAC^^_13.9 -#----------------------------- -# Note: This uses the standard Python idiom of accessing the -# attributes directly rather than going through a method call. -# See earlier in this chapter for examples of how this does -# not break encapsulation. -class Person: - def __init__(self, name = "", age = 0): - self.name = name - self.age = age -#----------------------------- -# Prefered: dude = Person("Jason", 23) -dude = Person() -dude.name = "Jason" -dude.age = 23 -print "%s is age %d." % (dude.name, dude.age) -#----------------------------- -class Employee(Person): - pass -#----------------------------- -# Prefered: empl = Employee("Jason", 23) -emp = Employee() -empl.name = "Jason" -empl.age = 23 -print "%s is age %d." % (empl.name, empl.age) -#----------------------------- - -# ^^PLEAC^^_13.10 -#----------------------------- -# This doesn't need to be done since if 'method' doesn't -# exist in the Class it will be looked for in its BaseClass(es) -class Class(BaseClass): - def method(self, *args, **kwargs): - BaseClass.method(self, *args, **kwargs) - -# This lets you pick the specific method in one of the base classes -class Class(BaseClass1, BaseClass2): - def method(self, *args, **kwargs): - BaseClass2.method(self, *args, **kwargs) - -# This looks for the first method in the base class(es) without -# specifically knowing which base class. This reimplements -# the default action so isn't really needed. -class Class(BaseClass1, BaseClass2, BaseClass3): - def method(self, *args, **kwargs): - for baseclass in self.__class__.__bases__: - f = getattr(baseclass, "method") - if f is not None: - return f(*args, **kwargs) - raise NotImplementedError("method") - -#----------------------------- -self.meth() # Call wherever first meth is found - -Where.meth(self) # Call in the base class "Where" - -# XXX Does Perl only have single inheritence? Or does -# it check all base classes? No directly equivalent way -# to do this in Python, but see above. -#----------------------------- -import time - -# The Perl code calls a private '_init' function, but in -# Python there's need for the complexity of 'new' mechanism -# so it's best just to put the '_init' code in '__init__'. -class Class: - def __init__(self, *args): - # init data fields - self.START = time.time() - self.AGE = 0 - self.EXTRA = args # anything extra -#----------------------------- -obj = Widget(haircolor = "red", freckles = 121) -#----------------------------- -class Class(Base1, Base2, Base3): - def __init__(self, *args, **kwargs): - for base in self.__class__.__bases__: - f = getattr(base, "__init__") - if f is not None: - f(self, *args, **kwargs) -#----------------------------- - -# ^^PLEAC^^_13.11 -#----------------------------- -# NOTE: Python prefers direct attribute lookup rather than -# method calls. Python 2.2 will introduce a 'get_set' which -# *may* be equivalent, but I don't know enough about it. So -# instead I'll describe a class that lets you restrict access -# to only specific attributes. - -class Private: - def __init__(self, names): - self.__names = names - self.__data = {} - def __getattr__(self, name): - if name in self.__names: - return self.__data[name] - raise AttributeError(name) - def __setattr__(self, name, value): - if name.startswith("_Private"): - self.__dict__[name] = value - return - if name in self.__names: - self.__data[name] = value - return - raise TypeError("cannot set the attribute %r" % (name,)) - -class Person(Private): - def __init__(self, parent = None): - Private.__init__(self, ["name", "age", "peers", "parent"]) - self.parent = parent - def new_child(self): - return Person(self) -#----------------------------- -dad = Person() -dad.name = "Jason" -dad.age = 23 -kid = dad.new_child() -kid.name = "Rachel" -kid.age = 2 -print "Kid's parent is", kid.parent.name -#=>Kid's parent is Jason - -# ^^PLEAC^^_13.12 -#----------------------------- -## XXX No clue on what this does. For that matter, what's -## "The Data Inheritance Problem"? - -# ^^PLEAC^^_13.13 -#----------------------------- -node.NEXT = node -#----------------------------- -# This is not a faithful copy of the Perl code, but it does -# show how to have the container's __del__ remove cycles in -# its contents. Note that Python 2.0 includes a garbage -# collector that is able to remove these sorts of cycles, but -# it's still best to prevent cycles in your code. -class Node: - def __init__(self, value = None): - self.next = self - self.prev = self - self.value = value - -class Ring: - def __init__(self): - self.ring = None - self.count = 0 - - def __str__(self): - # Helpful when debugging, to print the contents of the ring - s = "#%d: " % self.count - x = self.ring - if x is None: - return s - values = [] - while True: - values.append(x.value) - x = x.next - if x is self.ring: - break - return s + " -> ".join(map(str, values)) + " ->" - - def search(self, value): - node = self.ring - while True: - if node.value == value: - return node - node = node.next - if node is self.ring: - break - - def insert_value(self, value): - node = Node(value) - if self.ring is not None: - node.prev, node.next = self.ring.prev, self.ring - self.ring.prev.next = self.ring.prev = node - self.ring = node - self.count += 1 - - def delete_value(self, value): - node = self.search(value) - if node is not None: - self.delete_node(node) - - def delete_node(self, node): - if node is node.next: - node.next = node.prev = None - self.ring = None - else: - node.prev.next, node.next.prev = node.next, node.prev - if node is self.ring: - self.ring = node.next - self.count -= 1 - - def __del__(self): - while self.ring is not None: - self.delete_node(self.ring) - -COUNT = 1000 -for rep in range(20): - r = Ring() - for i in range(COUNT): - r.insert_value(i) -#----------------------------- - -# ^^PLEAC^^_13.14 -#----------------------------- -import UserString -class MyString(UserString.UserString): - def __cmp__(self, other): - return cmp(self.data.upper(), other.upper()) - -class Person: - def __init__(self, name, idnum): - self.name = name - self.idnum = idnum - def __str__(self): - return "%s (%05d)" % (self.name.lower().capitalize(), self.idnum) - -#----------------------------- -class TimeNumber: - def __init__(self, hours, minutes, seconds): - assert minutes < 60 and seconds < 60 - self.hours = hours - self.minutes = minutes - self.seconds = seconds - def __str__(self): - return "%d:%02d:%02d" % (self.hours, self.minutes, self.seconds) - def __add__(self, other): - seconds = self.seconds + other.seconds - minutes = self.minutes + other.minutes - hours = self.hours + other.hours - if seconds >= 60: - seconds %= 60 - minutes += 1 - if minutes >= 60: - minutes %= 60 - hours += 1 - return TimeNumber(hours, minutes, seconds) - - def __sub__(self, other): - raise NotImplementedError - - def __mul__(self, other): - raise NotImplementedError - - def __div__(self, other): - raise NotImplementedError - -t1 = TimeNumber(0, 58, 59) -sec = TimeNumber(0, 0, 1) -min = TimeNumber(0, 1, 0) -print t1 + sec + min + min -# 1:01:00 - -#----------------------------- -# For demo purposes only - the StrNum class is superfluous in this -# case as plain strings would give the same result. -class StrNum: - def __init__(self, value): - self.value = value - - def __cmp__(self, other): # both <=> and cmp - # providing <=> gives us <, ==, etc. for free. - # __lt__, __eq__, and __gt__ can also be individually specified - return cmp(self.value, other.value) - - def __str__(self): # "" - return self.value - - def __nonzero__(self, other): # bool - return bool(self.value) - - def __int__(self, other): # 0+ - return int(self.value) - - def __add__(self, other): # + - return StrNum(self.value + other.value) - - def __radd__(self, other): # +, inverted - return StrNum(other.value + self.value) - - def __mul__(self, other): # * - return StrNum(self.value * other) - - def __rmul__(self, other): # *, inverted - return StrNum(self.value * other) - - -def demo(): - # show_strnum - demo operator overloading - x = StrNum("Red") - y = StrNum("Black") - z = x + y - r = z * 3 - print "values are %s, %s, %s, and %s" % (x, y, z, r) - if x < y: - s = "LT" - else: - s = "GE" - print x, "is", s, y - -if __name__ == "__main__": - demo() -# values are Red, Black, RedBlack, and RedBlackRedBlackRedBlack -# Red is GE Black - -#----------------------------- -#!/usr/bin/env python -# demo_fixnum - show operator overloading - -# sum of STRFixNum: 40 and STRFixNum: 12 is STRFixNum: 52 -# product of STRFixNum: 40 and STRFixNum: 12 is STRFixNum: 480 -# STRFixNum: 3 has 0 places -# div of STRFixNum: 40 by STRFixNum: 12 is STRFixNum: 3.33 -# square of that is STRFixNum: 11.11 - -# This isn't excatly the same as the original Perl code since -# I couldn't figure out why the PLACES variable was used. -#----------------------------- -import re -_places_re = re.compile(r"\.(\d+)") - -default_places = 0 - -class FixNum: - def __init__(self, value, places = None): - self.value = value - if places is None: - # get from the value - m = _places_re.search(str(value)) - if m: - places = int(m.group(1)) - else: - places = default_places - self.places = places - - def __add__(self, other): - return FixNum(self.value + other.value, - max(self.places, other.places)) - - def __mul__(self, other): - return FixNum(self.value * other.value, - max(self.places, other.places)) - - def __div__(self, other): - # Force to use floating point, since 2/3 in Python is 0 - # Don't use float() since that will convert strings - return FixNum((self.value+0.0) / other.value, - max(self.places, other.places)) - - def __str__(self): - return "STR%s: %.*f" % (self.__class__.__name__, - self.places, self.value) - def __int__(self): - return int(self.value) - - def __float__(self): - return self.value - -def demo(): - x = FixNum(40) - y = FixNum(12, 0) - - print "sum of", x, "and", y, "is", x+y - print "product of", x, "and", y, "is", x*y - - z = x/y - print "%s has %d places" % (z, z.places) - if not z.places: - z.places = 2 - - print "div of", x, "by", y, "is", z - print "square of that is ", z*z - -if __name__ == "__main__": - demo() - - -# ^^PLEAC^^_13.15 -# You can't tie a variable, but you can use properties. -import itertools -class ValueRing(object): - def __init__(self, colours): - self.colourcycle = itertools.cycle(colours) - - def next_colour(self): - return self.colourcycle.next() - colour = property(next_colour) -vr = ValueRing(["red", "blue"]) -for i in range(6): - print vr.colour, -print - -# Note that you MUST refer directly to the property -x = vr.colour -print x, x, x -#------------------------------------- -# Ties are generally unnecessary in Python because of its strong OO support - -# The resulting code is MUCH shorter: -class AppendDict(dict): - def __setitem__(self, key, val): - if key in self: - self[key].append(val) - else: - super(AppendDict, self).__setitem__(key, [val]) -tab = AppendDict() -tab["beer"] = "guinness" -tab["food"] = "potatoes" -tab["food"] = "peas" - -for key, val in tab.items(): - print key, "=>", val -#------------------------------------- -class CaselessDict(dict): - def __setitem__(self, key, val): - super(CaselessDict, self).__setitem__(key.lower(), val) - def __getitem__(self, key): - return super(CaselessDict, self).__getitem__(key.lower()) - -tab = CaselessDict() -tab["VILLAIN"] = "big " -tab["herOine"] = "red riding hood" -tab["villain"] = "bad wolf" - -for key, val in tab.items(): - print key, "is", val -#=>villain is bad wolf -#=>heroine is red riding hood -#------------------------------------- -class RevDict(dict): - def __setitem__(self, key, val): - super(RevDict, self).__setitem__(key, val) - super(RevDict, self).__setitem__(val, key) - -tab = RevDict() -tab["red"] = "rojo" -tab["blue"] = "azul" -tab["green"] = "verde" -tab["evil"] = ("No Way!", "Way!") - -for key, val in tab.items(): - print key, "is", val -#=>blue is azul -#=>('No Way!', 'Way!') is evil -#=>rojo is red -#=>evil is ('No Way!', 'Way!') -#=>azul is blue -#=>verde is green -#=>green is verde -#=>red is rojo -#------------------------------------- -import itertools -for elem in itertools.count(): - print "Got", elem -#------------------------------------- -# You could use FileDispatcher from section 7.18 -tee = FileDispatcher(sys.stderr, sys.stdout) -#------------------------------------- -# @@PLEAC@@_14.0 - -# See http://www.python.org/doc/topics/database/ for Database Interfaces details. -# currently listed on http://www.python.org/doc/topics/database/modules/ -# -# DB/2, Informix, Interbase, Ingres, JDBC, MySQL, pyodbc, mxODBC, ODBC Interface, -# DCOracle, DCOracle2, PyGresQL, psycopg, PySQLite, sapdbapi, Sybase, ThinkSQL. -# - -# @@PLEAC@@_14.1 -#------------------------------------- -import anydbm -filename = "test.db" -try: - db = anydbm.open(filename) -except anydbm, err: - print "Can't open %s: %s!" % (filename, err) - -db["key"] = "value" # put value into database -if "key" in db: # check whether in database - val = db.pop("key") # retrieve and remove from database -db.close() # close the database -#------------------------------------- -# download the following standalone program -#!/usr/bin/python -# userstats - generates statistics on who logged in. -# call with an argument to display totals - -import sys, os, anydbm, re - -db_file = '/tmp/userstats.db' # where data is kept between runs - -try: - db = anydbm.open(db_file,'c') # open, create if it does not exist -except: - print "Can't open db %s: %s!" % (db_file, sys.exc_info()[1]) - sys.exit(1) - -if len(sys.argv) > 1: - if sys.argv[1] == 'ALL': - userlist = db.keys() - else: - userlist = sys.argv[1:] - userlist.sort() - for user in userlist: - if db.has_key(user): - print "%s\t%s" % (user, db[user]) - else: - print "%s\t%s" % (user, 0) -else: - who = os.popen('who').readlines() # run who(1) - if len(who)<1: - print "error running who" # exit - sys.exit(1) - # extract username (first thin on the line) and update - user_re = re.compile("^(\S+)") - for line in who: - fnd = user_re.search(line) - if not fnd: - print "Bad line from who: %s" % line - sys.exit(1) - user = fnd.groups()[0] - if not db.has_key(user): - db[user] = "0" - db[user] = str(int(db[user])+1) # only strings are allowed -db.close() - - - - -# @@PLEAC@@_14.2 -# Emptying a DBM File - -import anydbm - -try: - db = anydbm.open(FILENAME,'w') # open, for writing -except anydbm.error, err: - print "Can't open db %s: %s!" % (filename, err) - raise SystemExit(1) - -db.clear() -db.close() -# ------------------------------- -try: - db = anydbm.open(filename,'n') # open, always create a new empty db -except anydbm.error, err: - print "Can't open db %s: %s!" % (filename, err) - raise SystemExit(1) - -db.close() -# ------------------------------- -import os -try: - os.remove(FILENAME) -except OSError, err: - print "Couldn't remove %s to empty the database: %s!" % (FILENAME, - err) - raise SystemExit - -try: - db = anydbm.open(FILENAME,'n') # open, flways create a new empty db -except anydbm.error, err: - print "Couldn't create %s database: %s!" % (FILENAME, err) - raise SystemExit - -# @@PLEAC@@_14.3 -# Converting Between DBM Files - -# download the following standalone program -#!/usr/bin/python -# db2gdbm: converts DB to GDBM - -import sys -import dbm, gdbm - -if len(sys.argv)<3: - print "usage: db2gdbm infile outfile" - sys.exit(1) - -(infile, outfile) = sys.argv[1:] - -# open the files -try: - db_in = dbm.open(infile) -except: - print "Can't open infile %s: %s!" % (infile, sys.exc_info()[1]) - sys.exit(1) -try: - db_out = dbm.open(outfile,"n") -except: - print "Can't open outfile %s: %s!" % (outfile, sys.exc_info()[1]) - sys.exit(1) - -# copy (don't use db_out = db_in because it's slow on big databases) -# is this also so for python ? -for k in db_in.keys(): - db_out[k] = db_in[k] - -# these close happen automatically at program exit -db_out.close() -db_in.close() - - - -# @@PLEAC@@_14.4 - -OUTPUT.update(INPUT1) -OUTPUT.update(INPUT2) - -OUTPUT = anydbm.open("OUT","n") -for INPUT in (INPUT1, INPUT2, INPUT1): - for key, value in INPUT.iteritems(): - if OUTPUT.has_key(key): - # decide which value to use and set OUTPUT[key] if necessary - print "key %s already present: %s, new: %s" % ( - key, OUTPUT[key], value ) - else: - OUTPUT[key] = value - -# @@PLEAC@@_14.5 -# On systems where the Berkeley DB supports it, dbhash takes an -# "l" flag: -import dbhash -dbhash.open("mydb.db", "cl") # 'c': create if doesn't exist - -# @@INCOMPLETE@@ - -# @@PLEAC@@_14.6 -# @@INCOMPLETE@@ -# @@INCOMPLETE@@ - -# @@PLEAC@@_14.7 -# @@INCOMPLETE@@ -# @@INCOMPLETE@@ - -# @@PLEAC@@_14.8 -# shelve uses anydbm to access and chooses between DBMs. -# anydbm detect file formats automatically. -import shelve -db = shelve.open("celebrities.db") - -name1 = "Greg Stein" -name2 = "Greg Ward" - -# shelve uses pickle to convert objects into strings and back. -# This is automatic. -db[name1] = ["of ViewCVS fame", "gstein@lyra.org"] -db[name2] = ["of Distutils fame", "gward@python.net"] - -greg1 = db[name1] -greg2 = db[name2] - -print "Two Gregs: %x %x" % (id(greg1), id(greg2)) - -if greg1 == greg2: - print "You're having runtime fun with one Greg made two." -else: - print "No two Gregs are ever alike." - -# Changes to mutable entries are not written back by default. -# You can get the copy, change it, and put it back. -entry = db[name1] -entry[0] = "of Subversion fame" -db[name1] = entry - -# Or you can open shelve with writeback option. Then you can -# change mutable entries directly. (New in 2.3) -db = shelve.open("celebrities.db", writeback=True) -db[name2][0] = "of Optik fame" - -# However, writeback option can consume vast amounts of memory -# to do its magic. You can clear cache with sync(). -db.sync() -#----------------------------- - -# @@PLEAC@@_14.9 -# DON'T DO THIS. -import os as _os, shelve as _shelve - -_fname = "persist.db" -if not _os.path.exists(_fname): - var1 = "foo" - var2 = "bar" -_d = _shelve.open("persist.db") -globals().update(_d) - -print "var1 is %s; var2 is %s"%(var1, var2) -var1 = raw_input("New var1: ") -var2 = raw_input("New var2: ") - -for key, val in globals().items(): - if not key.startswith("_"): - _d[key] = val -# @@INCOMPLETE@@ - -# @@PLEAC@@_14.10 -#----------------------------- -import dbmodule - -dbconn = dbmodule.connect(arguments...) - -cursor = dbconn.cursor() -cursor.execute(sql) - -while True: - row = cursor.fetchone() - if row is None: - break - ... - -cursor.close() -dbconn.close() - -#----------------------------- -import MySQLdb -import pwd - -dbconn = MySQLdb.connect(db='dbname', host='mysqlserver.domain.com', - port=3306, user='user', passwd='password') - -cursor = dbconn.cursor() -cursor.execute("CREATE TABLE users (uid INT, login CHAR(8))") - -# Note: some databases use %s for parameters, some use ? or other -# formats -sql_fmt = "INSERT INTO users VALUES( %s, %s )" - -for userent in pwd.getpwall(): - # the second argument contains a list of parameters which will - # be quoted before being put in the query - cursor.execute(sql_fmt, (userent.pw_uid, userent.pw_name)) - -cursor.execute("SELECT * FROM users WHERE uid < 50") - -for row in cursor.fetchall(): - # NULL will be displayed as None - print ", ".join(map(str, row)) - -cursor.execute("DROP TABLE users") -cursor.close() -dbconn.close() -#----------------------------- - -# @@PLEAC@@_14.11 -# @@INCOMPLETE@@ -# @@INCOMPLETE@@ - -# @@PLEAC@@_15.1 -#----------------------------- -# 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. - - -# @@PLEAC@@_15.2 -##------------------ -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 - - -# @@PLEAC@@_15.3 - -# 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) - -# @@PLEAC@@_15.4 -# 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)) - -# @@PLEAC@@_15.5 - -# 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" - -# @@PLEAC@@_15.6 - -# 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 -#---------------------------------------- - -# @@PLEAC@@_15.7 -print "\aWake up!\n"; -#---------------------------------------- -# @@INCOMPLETE@@ - -# @@PLEAC@@_15.8 -# @@INCOMPLETE@@ -# @@INCOMPLETE@@ - -# @@PLEAC@@_15.9 -# On Windows -import msvcrt -if msvcrt.kbhit(): - c = msvcrt.getch - -# See http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/134892 -# @@INCOMPLETE@@ - - -# @@PLEAC@@_15.10 -#---------------------------------------- -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 -#---------------------------------------- - -# @@PLEAC@@_15.11 - -# 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") - -# @@PLEAC@@_15.12 -# @@INCOMPLETE@@ -# @@INCOMPLETE@@ - -# @@PLEAC@@_15.13 -#---------------------------------------- -# 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 - -# @@PLEAC@@_15.14 -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() - -# @@PLEAC@@_15.15 -# @@INCOMPLETE@@ -# @@INCOMPLETE@@ - -# @@PLEAC@@_15.16 -# @@INCOMPLETE@@ -# @@INCOMPLETE@@ - -# @@PLEAC@@_15.17 -# 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" - -# @@PLEAC@@_15.18 -# @@INCOMPLETE@@ -# @@INCOMPLETE@@ - -# @@PLEAC@@_15.19 -# @@INCOMPLETE@@ -# @@INCOMPLETE@@ - - -# @@PLEAC@@_16.1 -import popen2 - -# other popen methods than popen4 can lead to deadlocks -# if there is much data on stdout and stderr - -(err_out, stdin) = popen2.popen4("program args") -lines = err_out.read() # collect output into one multiline string - -(err_out, stdin) = popen2.popen4("program args") -lines = err_out.readlines() # collect output into a list, one line per element - -#----------------------------- - -(err_out, stdin) = popen2.popen4("program args") -output = [] -while True: - line = err_out.readline() - if not line: - break - output.appen(line) -output = ''.join(output) - -# @@PLEAC@@_16.2 -import os -myfile = "foo.txt" -status = os.system("vi %s" % myfile) - -#----------------------------- -import os -os.system("cmd1 args | cmd2 | cmd3 >outfile") -os.system("cmd args <infile >outfile 2>errfile") - -status = os.system("%s %s %s" % (program, arg1, arg2)) -if status != 0: - print "%s exited funny: %s" % (program, status) - raise SystemExit - - -# @@PLEAC@@_16.3 -# ----------------------------- -import os -import sys -import glob - -args = glob.glob("*.data") -try: - os.execvp("archive", args) -except OSError, e: - print "Couldn't replace myself with archive: %s" % err - raise SystemExit - -# The error message does not contain the line number like the "die" in -# perl. But if you want to show more information for debugging, you can -# delete the try...except and you get a nice traceback which shows all -# line numbers and filenames. - -# ----------------------------- -os.execvp("archive", ["accounting.data"]) - -# @@PLEAC@@_16.4 -# ------------------------- -# Read from a child process - -import sys -import popen2 -pipe = popen2.Popen4("program arguments") -pid = pipe.pid -for line in pipe.fromchild.readlines(): - sys.stdout.write(line) - -# Popen4 provides stdout and stderr. -# This avoids deadlocks if you get data -# from both streams. -# -# If you don't need the pid, you -# can use popen2.popen4(...) - -# ----------------------------- -# Write to a child process - -import popen2 - -pipe = popen2.Popen4("gzip > foo.gz") -pid = pipe.pid -pipe.tochild.write("Hello zipped world!\n") -pipe.tochild.close() # programm will get EOF on STDIN - -# @@PLEAC@@_16.5 -class OutputFilter(object): - def __init__(self, target, *args, **kwds): - self.target = target - self.setup(*args, **kwds) - self.textbuffer = "" - - def setup(self, *args, **kwds): - pass - - def write(self, data): - if data.endswith("\n"): - data = self.process(self.textbuffer + data) - self.textbuffer = "" - if data is not None: - self.target.write(data) - else: - self.textbuffer += data - - def process(self, data): - return data - -class HeadFilter(OutputFilter): - def setup(self, maxcount): - self.count = 0 - self.maxcount = maxcount - - def process(self, data): - if self.count < self.maxcount: - self.count += 1 - return data - -class NumberFilter(OutputFilter): - def setup(self): - self.count=0 - - def process(self, data): - self.count += 1 - return "%s: %s"%(self.count, data) - -class QuoteFilter(OutputFilter): - def process(self, data): - return "> " + data - -import sys -f = HeadFilter(sys.stdout, 100) -for i in range(130): - print>>f, i - -print - -txt = """Welcome to Linux, version 2.0.33 on a i686 - -"The software required `Windows 95 or better', -so I installed Linux." """ -f1 = NumberFilter(sys.stdout) -f2 = QuoteFilter(f1) -for line in txt.split("\n"): - print>>f2, line -print -f1 = QuoteFilter(sys.stdout) -f2 = NumberFilter(f1) -for line in txt.split("\n"): - print>>f2, line - - -# @@PLEAC@@_16.6 -# This script accepts several filenames -# as argument. If the file is zipped, unzip -# it first. Then read each line if the file -import os -import sys -import popen2 - -for file in sys.argv[1:]: - if file.endswith(".gz") or file.endswith(".Z"): - (stdout, stdin) = popen2.popen2("gzip -dc '%s'" % file) - fd = stdout - else: - fd = open(file) - for line in fd: - # .... - sys.stdout.write(line) - fd.close() -#----------------------------- - -#----------------------------- -# Ask for filename and open it -import sys -print "File, please?" -line = sys.stdin.readline() -file = line.strip() # chomp -open(file) - -# @@PLEAC@@_16.7 -# Execute foo_command and read the output - -import popen2 -(stdout_err, stdin) = popen2.popen4("foo_command") -for line in stdout_err.readlines(): - # .... - -# @@PLEAC@@_16.8 -# Open command in a pipe -# which reads from stdin and writes to stdout - -import popen2 -pipe = popen2.Popen4("wc -l") # Unix command -pipe.tochild.write("line 1\nline 2\nline 3\n") -pipe.tochild.close() -output = pipe.fromchild.read() - -# @@PLEAC@@_16.9 - -# popen3: get stdout and stderr of new process -# Attetion: This can lead to deadlock, -# since the buffer of stderr or stdout might get filled. -# You need to use select if you want to avoid this. - -import popen2 -(child_stdout, child_stdin, child_stderr) = popen2.popen3(...) - -# @@PLEAC@@_16.10 -# @@INCOMPLETE@@ -# @@INCOMPLETE@@ - -# @@PLEAC@@_16.11 -# @@INCOMPLETE@@ -# @@INCOMPLETE@@ - -# @@PLEAC@@_16.12 -# @@INCOMPLETE@@ -# @@INCOMPLETE@@ - -# @@PLEAC@@_16.13 -# -# Print available signals and their value -# See "man signal" "man kill" on unix. - -import signal -for name in dir(signal): - if name.startswith("SIG"): - value = getattr(signal, name) - print "%s=%s" % (name, value) - -# @@PLEAC@@_16.14 -# You can send signals to processes -# with os.kill(pid, signal) - - -# @@PLEAC@@_16.15 -import signal - -def get_sig_quit(signum, frame): - .... - -signal.signal(signal.SIGQUIT, get_sig_quit) # Install handler - -signal.signal(signal.SIGINT, signal.SIG_IGN) # Ignore this signal -signal.signal(signal.SIGSTOP, signal.SIG_DFL) # Restore to default handling - -# @@PLEAC@@_16.16 -# Example of handler: User must Enter Name ctrl-c does not help - -import sys -import signal - -def ding(signum, frame): - print "\aEnter your name!" - return - -signal.signal(signal.SIGINT, ding) -print "Please enter your name:" - -name = "" -while not name: - try: - name = sys.stdin.readline().strip() - except: - pass - -print "Hello: %s" % name - -# @@PLEAC@@_16.17 -# @@INCOMPLETE@@ -# @@INCOMPLETE@@ - -# @@PLEAC@@_16.18 -import signal - -# ignore signal INT -signal.signal(signal.SIGINT, signal.SIG_IGN) - -# Install signal handler -def tsktsk(signum, frame): - print "..." - -signal.signal(signal.SIGINT, tsktsk) - -# @@PLEAC@@_16.19 -# @@INCOMPLETE@@ -# @@INCOMPLETE@@ - -# @@PLEAC@@_16.20 -# @@INCOMPLETE@@ -# @@INCOMPLETE@@ - -# @@PLEAC@@_16.21 -import signal - -def handler(signum, frame): - raise "timeout" - -signal.signal(signal.SIGALRM, handler) - -try: - signal.alarm(5) # signal.alarm(3600) - - # long-time operation - while True: - print "foo" - - signal.alarm(0) -except: - signal.alarm(0) - print "timed out" -else: - print "no time out" - -# @@PLEAC@@_16.22 -# @@INCOMPLETE@@ -# @@INCOMPLETE@@ - -# @@PLEAC@@_17.0 -# Socket Programming (tcp/ip and udp/ip) - -import socket - -# Convert human readable form to 32 bit value -packed_ip = socket.inet_aton("208.146.240.1") -packed_ip = socket.inet_aton("www.oreilly.com") - -# Convert 32 bit value to ip adress -ip_adress = socket.inet_ntoa(packed_ip) - -# Create socket object -socketobj = socket(family, type) # Example socket.AF_INT, socket.SOCK_STREAM - -# Get socketname -socketobj.getsockname() # Example, get port adress of client - -# @@PLEAC@@_17.1 - -# Example: Connect to a server (tcp) -# Connect to a smtp server at localhost and send an email. -# For real applications you should use smtplib. - -import socket -s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) -s.connect(("localhost", 25)) # SMTP -print s.recv(1024) -s.send("mail from: <pleac@localhost>\n") -print s.recv(1024) -s.send("rcpt to: <guettli@localhost>\n") -print s.recv(1024) -s.send("data\n") -print s.recv(1024) -s.send("From: Python Lover\nSubject: Python is better then perl\n\nYES!\n.\n") -print s.recv(1024) -s.close() - -# @@PLEAC@@_17.2 - -# Create a Server, calling handler for every client -# You can test it with "telnet localhost 1029" - -from SocketServer import TCPServer -from SocketServer import BaseRequestHandler - -class MyHandler(BaseRequestHandler): - def handle(self): - print "I got an request" - -server = TCPServer(("127.0.0.1", 1029), MyHandler) -server.serve_forever() - -# @@PLEAC@@_17.3 -# This is the continuation of 17.2 - -import time -from SocketServer import TCPServer -from SocketServer import BaseRequestHandler - -class MyHandler(BaseRequestHandler): - def handle(self): - # self.request is the socket object - print "%s I got an request from ip=%s port=%s" % ( - time.strftime("%Y-%m-%d %H:%M:%S"), - self.client_address[0], - self.client_address[1] - ) - self.request.send("What is your name?\n") - bufsize=1024 - response=self.request.recv(bufsize).strip() # or recv(bufsize, flags) - data_to_send="Welcome %s!\n" % response - self.request.send(data_to_send) # or send(data, flags) - print "%s connection finnished" % self.client_address[0] - -server = TCPServer(("127.0.0.1", 1028), MyHandler) -server.serve_forever() - -# ----------------- -# Using select - -import select -import socket - -in_list = [] -in_list.append(mysocket) -in_list.append(myfile) -# ... - -out_list = [] -out_list.append(...) - -except_list = [] -except_list.append(...) - -(in_, out_, exc_) = select.select(in_list, out_list, except_list, timeout) - -for fd in in_: - print "Can read", fd -for fd in out_: - print "Can write", fd -for fd in exc_: - print "Exception on", fd - -# Missing: setting TCP_NODELAY - -# @@PLEAC@@_17.4 - -import socket -# Set up a UDP socket -s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) -# send -MSG = 'Hello' -HOSTNAME = '127.0.0.1' -PORTNO = 10000 -s.connect((HOSTNAME, PORTNO)) -if len(MSG) != s.send(MSG): - # where to get error message "$!". - print "cannot send to %s(%d):" % (HOSTNAME,PORTNO) - raise SystemExit(1) -MAXLEN = 1024 -(data,addr) = s.recvfrom(MAXLEN) -s.close() -print '%s(%d) said "%s"' % (addr[0],addr[1], data) - -# download the following standalone program -#!/usr/bin/python -# clockdrift - compare another system's clock with this one - -import socket -import struct -import sys -import time - -if len(sys.argv)>1: - him = sys.argv[1] -else: - him = '127.1' - -SECS_of_70_YEARS = 2208988800 - -s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) -s.connect((him,socket.getservbyname('time','udp'))) -s.send('') -(ptime, src) = s.recvfrom(4) -host = socket.gethostbyaddr(src[0]) -delta = struct.unpack("!L", ptime)[0] - SECS_of_70_YEARS - time.time() -print "Clock on %s is %d seconds ahead of this one." % (host[0], delta) - - - -# @@PLEAC@@_17.5 - -import socket -import sys - -s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) -try: - s.bind(('', server_port)) -except socket.error, err: - print "Couldn't be a udp server on port %d : %s" % ( - server_port, err) - raise SystemExit - -while True: - datagram = s.recv(MAX_TO_READ) - if not datagram: - break - # do something -s.close() - -# or -import SocketServer - -class handler(SocketServer.DatagramRequestHandler): - def handle(self): - # do something (with self.request[0]) - -s = SocketServer.UDPServer(('',10000), handler) -s.serve_forever() - -# download the following standalone program -#!/usr/bin/python -# udpqotd - UDP message server - -import SocketServer - -PORTNO = 5151 - -class handler(SocketServer.DatagramRequestHandler): - def handle(self): - newmsg = self.rfile.readline().rstrip() - print "Client %s said ``%s''" % (self.client_address[0], newmsg) - self.wfile.write(self.server.oldmsg) - self.server.oldmsg = newmsg - -s = SocketServer.UDPServer(('',PORTNO), handler) -print "Awaiting UDP messages on port %d" % PORTNO -s.oldmsg = "This is the starting message." -s.serve_forever() - - -# download the following standalone program -#!/usr/bin/python -# udpmsg - send a message to the udpquotd server - -import socket -import sys - -MAXLEN = 1024 -PORTNO = 5151 -TIMEOUT = 5 - -server_host = sys.argv[1] -msg = " ".join(sys.argv[2:]) - -sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) -sock.settimeout(TIMEOUT) -sock.connect((server_host, PORTNO)) -sock.send(msg) -try: - msg = sock.recv(MAXLEN) - ipaddr, port = sock.getpeername() - hishost = socket.gethostbyaddr(ipaddr) - print "Server %s responded ``%s''" % ( hishost[0], msg) -except: - print "recv from %s failed (timeout or no server running)." % ( - server_host ) -sock.close() - - -# @@PLEAC@@_17.6 - -import socket -import os, os.path - -if os.path.exists("/tmp/mysock"): - os.remove("/tmp/mysock") - -server = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM) -server.bind("/tmp/mysock") - -client = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM) -client.connect("/tmp/mysock") - -# @@PLEAC@@_17.7 - -ipaddr, port = s.getpeername() -hostname, aliaslist, ipaddrlist = socket.gethostbyaddr(ipaddr) -ipaddr = socket.gethostbyname('www.python.org') -# '194.109.137.226' -hostname, aliaslist, ipaddrlist = socket.gethostbyname_ex('www.python.org') -# ('fang.python.org', ['www.python.org'], ['194.109.137.226']) -socket.gethostbyname_ex('www.google.org') -# ('www.l.google.com', ['www.google.org', 'www.google.com'], -# ['64.233.161.147','64.233.161.104', '64.233.161.99']) - -# @@PLEAC@@_17.8 - -import os - -kernel, hostname, release, version, hardware = os.uname() - -import socket - -address = socket.gethostbyname(hostname) -hostname = socket.gethostbyaddr(address) -hostname, aliaslist, ipaddrlist = socket.gethostbyname_ex(hostname) -# e.g. ('lx3.local', ['lx3', 'b70'], ['192.168.0.13', '192.168.0.70']) - -# @@PLEAC@@_17.9 - -socket.shutdown(0) # Further receives are disallowed -socket.shutdown(1) # Further sends are disallowed. -socket.shutdown(2) # Further sends and receives are disallowed. - -# - -server.send("my request\n") # send some data -server.shutdown(1) # send eof; no more writing -answer = server.recv(1000) # but you can still read - -# @@PLEAC@@_17.10 -# @@INCOMPLETE@@ -# @@INCOMPLETE@@ - -# @@PLEAC@@_17.11 -# @@INCOMPLETE@@ -# @@INCOMPLETE@@ - -# @@PLEAC@@_17.12 -# @@INCOMPLETE@@ -# @@INCOMPLETE@@ - -# @@PLEAC@@_17.13 -# @@INCOMPLETE@@ -# @@INCOMPLETE@@ - -# @@PLEAC@@_17.14 -# @@INCOMPLETE@@ -# @@INCOMPLETE@@ - -# @@PLEAC@@_17.15 -# @@INCOMPLETE@@ -# @@INCOMPLETE@@ - -# @@PLEAC@@_17.16 -#------------------------------ -# Restart programm on signal SIGHUP -# Script must be executable: chmod a+x foo.py - -#!/usr/bin/env python -import os -import sys -import time -import signal - -def phoenix(signum, frame): - print "Restarting myself: %s %s" % (self, args) - os.execv(self, args) - -self = os.path.abspath(sys.argv[0]) -args = sys.argv[:] -signal.signal(signal.SIGHUP, phoenix) - -while True: - print "work" - time.sleep(1) - -#-------------------- -# Read config file on SIGHUP -import signal - -config_file = "/usr/local/etc/myprog/server_conf.py" - -def read_config(): - execfile(config_file) - -signal.signal(signal.SIGHUP, read_config) - -# @@PLEAC@@_17.17 - -# chroot - -import os - -try: - os.chroot("/var/daemon") -except Exception: - print "Could not chroot" - raise SystemExit(1) - -#----------------------------- -# fork (Unix): Create a new process -# if pid == 0 --> parent process -# else child process - -import os - -pid = os.fork() -if pid: - print "I am the new child %s" % pid - raise SystemExit -else: - print "I am still the parent" - - -# ---------------------------- -# setsid (Unix): Create a new session -import os -id=os.setsid() - -# ---------------------------- -# Work until INT TERM or HUP signal is received -import time -import signal - -time_to_die = 0 - -def sighandler(signum, frame): - print "time to die" - global time_to_die - time_to_die = 1 - -signal.signal(signal.SIGINT, sighandler) -signal.signal(signal.SIGTERM, sighandler) -signal.signal(signal.SIGHUP, sighandler) - -while not time_to_die: - print "work" - time.sleep(1) - -# @@PLEAC@@_17.18 -# @@INCOMPLETE@@ -# @@INCOMPLETE@@ - -# @@PLEAC@@_18.1 - -import socket -try: - host_info = socket.gethostbyname_ex(name) - # (hostname, aliaslist, ipaddrlist) -except socket.gaierror, err: - print "Can't resolve hostname %s: %s" % (name, err[1]) - -# if you only need the first one -import socket -try: - address = socket.gethostbyname(name) -except socket.gaierror, err: - print "Can't resolve hostname %s: %s" % (name, err[1]) - -# if you have an ip address -try: - host_info = socket.gethostbyaddr(address) - # (hostname, aliaslist, ipaddrlist) -except socket.gaierror, err: - print "Can't resolve address %s: %s" % (address, err[1]) - -# checking back -import socket -try: - host_info = socket.gethostbyaddr(address) -except socket.gaierror, err: - print "Can't look up %s: %s" % (address, err[1]) - raise SystemExit(1) -try: - host_info = socket.gethostbyname_ex(name) -except: - print "Can't look up %s: %s" % (name, err[1]) - raise SystemExit(1) - -found = address in host_info[2] - -# use dnspython for more complex jobs. -# download the following standalone program -#!/usr/bin/python -# mxhost - find mx exchangers for a host - -import sys - -import dns -import dns.resolver - -answers = dns.resolver.query(sys.argv[1], 'MX') -for rdata in answers: - print rdata.preference, rdata.exchange - - - -# download the following standalone program -#!/usr/bin/python -# hostaddrs - canonize name and show addresses - -import sys -import socket -name = sys.argv[1] -hent = socket.gethostbyname_ex(name) -print "%s aliases: %s => %s" % ( - hent[0], - len(hent[1])==0 and "None" or ",".join(hent[1]), - ",".join(hent[2]) ) - - -# @@PLEAC@@_18.2 -import ftplib -ftp = ftplib.FTP("ftp.host.com") -ftp.login(username, password) -ftp.cwd(directory) - -# get file -outfile = open(filename, "wb") -ftp.retrbinary("RETR %s" % filename, outfile.write) -outfile.close() - -# upload file -upfile = open(upfilename, "rb") -ftp.storbinary("STOR %s" % upfilename, upfile) -upfile.close() - -ftp.quit() - - -# @@PLEAC@@_18.3 -import smtplib -from email.MIMEText import MIMEText - -msg = MIMEText(body) -msg['From'] = from_address -msg['To'] = to_address -msg['Subject'] = subject - -mailer = smtplib.SMTP() -mailer.connect() -mailer.sendmail(from_address, [to_address], msg.as_string()) - -# @@PLEAC@@_18.4 -import nntplib - -# You can except nntplib.NNTPError to process errors -# instead of displaying traceback. - -server = nntplib.NNTP("news.example.com") -response, count, first, last, name = server.group("misc.test") -headers = server.head(first) -bodytext = server.body(first) -article = server.article(first) - -f = file("article.txt") -server.post(f) - -response, grouplist = server.list() -for group in grouplist: - name, last, first, flag = group - if flag == 'y': - pass # I can post to group - -# @@PLEAC@@_18.5 -import poplib - -pop = poplib.POP3("mail.example.com") -pop.user(username) -pop.pass_(password) -count, size = pop.stat() -for i in range(1, count+1): - reponse, message, octets = pop.retr(i) - # message is a list of lines - pop.dele(i) - -# You must quit, otherwise mailbox remains locked. -pop.quit() - -# @@PLEAC@@_18.6 - -import telnetlib - -tn = telnetlib.Telnet(hostname) - -tn.read_until("login: ") -tn.write(user + "\n") -tn.read_until("Password: ") -tn.write(password + "\n") -# read the logon message up to the prompt -d = tn.expect([prompt,], 10) -tn.write("ls\n") -files = d[2].split() -print len(files), "files" -tn.write("exit\n") -print tn.read_all() # blocks till eof - -# @@PLEAC@@_18.7 -# @@INCOMPLETE@@ -# @@INCOMPLETE@@ - -# @@PLEAC@@_18.8 -# @@INCOMPLETE@@ -# @@INCOMPLETE@@ - -# @@PLEAC@@_18.9 -# @@INCOMPLETE@@ -# @@INCOMPLETE@@ - -# @@PLEAC@@_19.0 -# Introduction -# -# There is no standard cgi/web framework in python, -# this is reason for ranting now and then. -# -# See `PyWebOff <http://pyre.third-bit.com/pyweb/index.html>`__ -# which compares CherryPy, Quixote, Twisted, WebWare and Zope -# Karrigell and print stantements. -# -# Then there is Nevow and Standalone ZPT. - -# @@PLEAC@@_19.1 -# Partial implementation of PLEAC Python section 19.1 -# Written by Seo Sanghyeon - -# Standard CGI module is where PERL shines. Python -# module, cgi, is nothing but a form parser. So it is -# not really fair to compare these two. But I hesitate -# to introduce any non-standard module. After all, -# which one should I choose? - -# I would stick to simple print statements. I believe -# the following is close to how these tasks are usually -# done in Python. - -#----------------------------- -#!/usr/bin/env python -# hiweb - using FieldStorage class to get at form data - -import cgi -form = cgi.FieldStorage() - -# get a value from the form -value = form.getvalue("PARAM_NAME") - -# print a standard header -print "Content-Type: text/html" -print - -# print a document -print "<P>You typed: <TT>%s</TT></P>" % ( - cgi.escape(value), - ) - -#----------------------------- -import cgi -form = cgi.FieldStorage() - -who = form.getvalue("Name") -phone = form.getvalue("Number") -picks = form.getvalue("Choices") - -# if you want to assure `picks' to be a list -picks = form.getlist("Choices") - -#----------------------------- -# Not Implemented - -# To implement -EXPIRES => '+3d', I need to study about -import cgi -import datetime - -time_format = "%a, %d %b %Y %H:%M:%S %Z" -print "Expires: %s" % ( - (datetime.datetime.now() - + datetime.timedelta(+3)).strftime(time_format) - ) -print "Date: %s" % (datetime.datetime.now().strftime(time_format)) -print "Content-Type: text/plain; charset=ISO-8859-1" - -#----------------------------- -# NOTES - -# CGI::param() is a multi-purpose function. Here I want to -# note which Python functions correspond to it. - -# PERL version 5.6.1, CGI.pm version 2.80. -# Python version 2.2.3. cgi.py CVS revision 1.68. - -# Assume that `form' is the FieldStorage instance. - -# param() with zero argument returns parameter names as -# a list. It is `form.keys()' in Python, following Python's -# usual mapping interface. - -# param() with one argument returns the value of the named -# parameter. It is `form.getvalue()', but there are some -# twists: - -# 1) A single value is passed. -# No problem. - -# 2) Multiple values are passed. -# PERL: in LIST context, you get a list. in SCALAR context, -# you get the first value from the list. -# Python: `form.getvalue()' returns a list if multiple -# values are passed, a raw value if a single value -# is passed. With `form.getlist()', you always -# get a list. (When a single value is passed, you -# get a list with one element.) With `form.getfirst()', -# you always get a value. (When multiple values are -# passed, you get the first one.) - -# 3) Parameter name is given, but no value is passed. -# PERL: returns an empty string, not undef. POD says this -# feature is new in 2.63, and was introduced to avoid -# "undefined value" warnings when running with the -# -w switch. -# Python: tricky. If you want black values to be retained, -# you should pass a nonzero `keep_blank_values' keyword -# argument. Default is not to retain blanks. In case -# values are not retained, see below. - -# 4) Even parameter name is never mentioned. -# PERL: returns undef. -# Python: returns None, or whatever you passed as the second -# argument, or `default` keyword argument. This is -# consistent with `get()' method of the Python mapping -# interface. - -# param() with more than one argument modifies the already -# set form data. This functionality is not available in Python -# cgi module. - - -# @@PLEAC@@_19.2 -# enable() from 'cgitb' module, by default, redirects traceback -# to the browser. It is defined as 'enable(display=True, logdir=None, -# context=5)'. - -# equivalent to importing CGI::Carp::fatalsToBrowser. -import cgitb -cgitb.enable() - -# to suppress browser output, you should explicitly say so. -import cgitb -cgitb.enable(display=False) - -# equivalent to call CGI::Carp::carpout with temporary files. -import cgitb -cgitb.enable(logdir="/var/local/cgi-logs/") - -# Python exception, traceback facilities are much richer than PERL's -# die and its friends. You can use your custom exception formatter -# by replacing sys.excepthook. (equivalent to CGI::Carp::set_message.) -# Default formatter is available as traceback.print_exc() in pure -# Python. In fact, what cgitb.enable() does is replacing excepthook -# to cgitb.handler(), which knows how to format exceptions to HTML. - -# If this is not enough, (usually this is enough!) Python 2.3 comes -# with a new standard module called 'logging', which is complex, but -# very flexible and entirely customizable. - -# @@PLEAC@@_19.3 -# -# download the following standalone program -#!/usr/bin/python -# webwhoami - show web users id -import getpass -print "Content-Type: text/plain\n" -print "Running as %s\n" % getpass.getuser() - - - -# STDOUT/ERR flushing -# -# In contrast to what the perl cookbook says, modpython.org tells -# STDERR is buffered too. - -# @@PLEAC@@_19.4 -# @@INCOMPLETE@@ -# @@INCOMPLETE@@ - -# @@PLEAC@@_19.5 - -# use mod_python in the Apache web server. - -# Load the module in httpd.conf or apache.conf - -LoadModule python_module libexec/mod_python.so - -<Directory /some/directory/htdocs/test> - AddHandler mod_python .py - PythonHandler mptest - PythonDebug On -</Directory> - -# test.py file in /some/directory/htdocs/test -from mod_python import apache - -def handler(req): - req.write("Hello World!") - return apache.OK - -# @@PLEAC@@_19.6 - -import os -os.system("command %s %s" % (input, " ".join(files))) # UNSAFE - -# python doc lib cgi-security it says -# -# To be on the safe side, if you must pass a string gotten from a form to a shell -# command, you should make sure the string contains only alphanumeric characters, dashes, -# underscores, and periods. -import re -cmd = "command %s %s" % (input, " ".join(files)) -if re.search(r"[^a-zA-Z0-9._\-]", cmd): - print "rejected" - sys.exit(1) -os.system(cmd) -trans = string.maketrans(string.ascii_letters+string.digits+"-_.", - -# @@INCOMPLETE@@ -# @@INCOMPLETE@@ - -# @@PLEAC@@_19.7 -#----------------------------- -# This uses nevow's (http://nevow.com) stan; there's no standard -# way to generate HTML, though there are many implementations of -# this basic idea. -from nevow import tags as T -print T.ol[T.li['red'], T.li['blue'], T.li['green']] -# <ol><li>red</li><li>blue</li><li>green</li></ol> - -names = 'Larry Moe Curly'.split() -print T.ul[ [T.li(type="disc")[name] for name in names] ] -# <ul><li type="disc">Larry</li><li type="disc">Moe</li> -# <li type="disc">Curly</li></ul> -#----------------------------- -print T.li["alpha"] -# <li>alpha</li> - -print T.li['alpha'], T.li['omega'] -# <li>alpha</li> <li>omega</li> -#----------------------------- -states = { - "Wisconsin": [ "Superior", "Lake Geneva", "Madison" ], - "Colorado": [ "Denver", "Fort Collins", "Boulder" ], - "Texas": [ "Plano", "Austin", "Fort Stockton" ], - "California": [ "Sebastopol", "Santa Rosa", "Berkeley" ], -} - -print "<TABLE> <CAPTION>Cities I Have Known</CAPTION>"; -print T.tr[T.th('State'), T.th('Cities')] -for k in sorted(states.keys()): - print T.tr[ [T.th(k)] + [T.td(city) for city in sorted(states[k])] ] -print "</TABLE>"; -#----------------------------- -# <TABLE> <CAPTION>Cities I Have Known</CAPTION> -# -# <TR><TH>State</TH> <TH>Cities</TH></TR> -# -# <TR><TH>California</TH> <TD>Berkeley</TD> <TD>Santa Rosa</TD> -# -# <TD>Sebastopol</TD> </TR> -# -# <TR><TH>Colorado</TH> <TD>Boulder</TD> <TD>Denver</TD> -# -# <TD>Fort Collins</TD> </TR> -# -# <TR><TH>Texas</TH> <TD>Austin</TD> <TD>Fort Stockton</TD> -# -# <TD>Plano</TD></TR> -# -# <TR><TH>Wisconsin</TH> <TD>Lake Geneva</TD> <TD>Madison</TD> -# -# <TD>Superior</TD></TR> -# -# </TABLE> -#----------------------------- -print T.table[ - [T.caption['Cities I have Known'], - T.tr[T.th['State'], T.th['Cities']] ] + - [T.tr[ [T.th(k)] + [T.td(city) for city in sorted(states[k])]] - for k in sorted(states.keys())]] -#----------------------------- -# salcheck - check for salaries -import MySQLdb -import cgi - -form = cgi.FieldStorage() - -if 'limit' in form: - limit = int(form['limit'].value) -else: - limit = '' - -# There's not a good way to start an HTML/XML construct with stan -# without completing it. -print '<html><head><title>Salary Query</title></head><body>' -print T.h1['Search'] -print '<form>' -print T.p['Enter minimum salary', - T.input(type="text", name="limit", value=limit)] -print T.input(type="submit") -print '</form>' - -if limit: - dbconn = MySQLdb.connect(db='somedb', host='server.host.dom', - port=3306, user='username', - passwd='password') - cursor = dbconn.cursor() - cursor.execute(""" - SELECT name, salary FROM employees - WHERE salary > %s""", (limit,)) - - print T.h1["Results"] - print "<TABLE BORDER=1>" - - for row in cursor.fetchall(): - print T.tr[ [T.td(cell) for cell in row] ] - - print "</TABLE>\n"; - cursor.close() - dbconn.close() - -print '</body></html>' -#----------------------------- - -# @@PLEAC@@_19.8 -#----------------------------- -url = "http://python.org/pypi" -print "Location: %s\n" % url -raise SystemExit -#----------------------------- -# oreobounce - set a cookie and redirect the browser -import Cookie -import time - -c = Cookie.SimpleCookie() -c['filling'] = 'vanilla cr?me' -now = time.time() -future = now + 3*(60*60*24*30) # 3 months -expire_date = time.strftime('%a %d %b %Y %H:%M:%S GMT', future) -c['filling']['expires'] = expire_date -c['filling']['domain'] = '.python.org' - -whither = "http://somewhere.python.org/nonesuch.html" - -# Prints the cookie header -print 'Status: 302 Moved Temporarily' -print c -print 'Location:', whither -print - -#----------------------------- -#Status: 302 Moved Temporarily -#Set-Cookie: filling=vanilla%20cr%E4me; domain=.perl.com; -# expires=Tue, 21-Jul-1998 11:58:55 GMT -#Location: http://somewhere.perl.com/nonesuch.html -#----------------------------- -# os_snipe - redirect to a Jargon File entry about current OS -import os, re -dir = 'http://www.wins.uva.nl/%7Emes/jargon' -matches = [ - (r'Mac', 'm/Macintrash.html'), - (r'Win(dows )?NT', 'e/evilandrude.html'), - (r'Win|MSIE|WebTV', 'm/MicroslothWindows.html'), - (r'Linux', 'l/Linux.html'), - (r'HP-UX', 'h/HP-SUX.html'), - (r'SunOS', 's/ScumOS.html'), - (None, 'a/AppendixB.html'), - ] - -for regex, page in matches: - if not regex: # default - break - if re.search(regex, os.environ['HTTP_USER_AGENT']): - break -print 'Location: %s/%s\n' % (dir, page) -#----------------------------- -# There's no special way to print headers -print 'Status: 204 No response' -print -#----------------------------- -#Status: 204 No response -#----------------------------- - -# @@PLEAC@@_19.9 -# download the following standalone program -#!/usr/bin/python -# dummyhttpd - start a HTTP daemon and print what the client sends - -import SocketServer -# or use BaseHTTPServer, SimpleHTTPServer, CGIHTTPServer - -def adr_str(adr): - return "%s:%d" % adr - -class RequestHandler(SocketServer.BaseRequestHandler): - def handle(self): - print "client access from %s" % adr_str(self.client_address) - print self.request.recv(10000) - self.request.send("Content-Type: text/plain\n" - "Server: dymmyhttpd/1.0.0\n" - "\n...\n") - self.request.close() - - -adr = ('127.0.0.1', 8001) -print "Please contact me at <http://%s>" % adr_str(adr) -server = SocketServer.TCPServer(adr, RequestHandler) -server.serve_forever() -server.server_close() - - -# @@PLEAC@@_19.10 - -import Cookie -cookies = Cookie.SimpleCookie() -# SimpleCookie is more secure, but does not support all characters. -cookies["preference-name"] = "whatever you'd like" -print cookies - -# download the following standalone program -#!/usr/bin/python -# ic_cookies - sample CGI script that uses a cookie - -import cgi -import os -import Cookie -import datetime - -cookname = "favorite-ice-cream" # SimpleCookie does not support blanks -fieldname = "flavor" - -cookies = Cookie.SimpleCookie(os.environ.get("HTTP_COOKIE","")) -if cookies.has_key(cookname): - favorite = cookies[cookname].value -else: - favorite = "mint" - -form = cgi.FieldStorage() -if not form.has_key(fieldname): - print "Content-Type: text/html" - print "\n" - print "<html><body>" - print "<h1>Hello Ice Cream</h1>" - print "<form>" - print 'Please select a flavor: <input type="text" name="%s" value="%s" />' % ( - fieldname, favorite ) - print "</form>" - print "<hr />" - print "</body></html>" -else: - favorite = form[fieldname].value - cookies[cookname] = favorite - expire = datetime.datetime.now() + datetime.timedelta(730) - cookies[cookname]["expires"] = expire.strftime("%a, %d %b %Y %H:00:00 GMT") - cookies[cookname]["path"] = "/" - print "Content-Type: text/html" - print cookies - print "\n" - print "<html><body>" - print "<h1>Hello Ice Cream</h1>" - print "<p>You chose as your favorite flavor \"%s\"</p>" % favorite - print "</body></html>" - - -# @@PLEAC@@_19.11 -# @@INCOMPLETE@@ -# @@INCOMPLETE@@ - -# @@PLEAC@@_19.12 -# @@INCOMPLETE@@ -# @@INCOMPLETE@@ - -# @@PLEAC@@_19.13 -#----------------------------- -# first open and exclusively lock the file -import os, cgi, fcntl, cPickle -fh = open('/tmp/formlog', 'ab') -fcntl.flock(fh.fileno(), fcntl.LOCK_EX) - -form = cgi.FieldStorage() -# This doesn't produce a readable file; we copy the environment so -# that we save a plain dictionary (os.environ is a dictionary-like -# object). -cPickle.dump((form, os.environ.copy()) fh) -fh.close() -#----------------------------- -import cgi, smtplib, sys - -form = cgi.FieldStorage() -email = """\ -From: %S -To: hisname@hishost.com -Subject: mailed form submission - -""" % sys.argv[0] - -for key in form: - values = form[key] - if not isinstance(values, list): - value = [values.value] - else: - value = [v.value for v in values] - for item in values: - email += '\n%s: %s' % (key, value) - -server = smtplib.SMTP('localhost') -server.sendmail(sys.argv[0], ['hisname@hishost.com'], email) -server.quit() -#----------------------------- -# @@INCOMPLETE@@ I don't get the point of these: -# param("_timestamp", scalar localtime); -# param("_environs", %ENV); -#----------------------------- -import fcntl, cPickle -fh = open('/tmp/formlog', 'rb') -fcntl.flock(fh.fileno(), fcntl.LOCK_SH) - -count = 0 -while True: - try: - form, environ = cPickle.load(fh) - except EOFError: - break - if environ.get('REMOTE_HOST').endswith('perl.com'): - continue - if 'items requested' in form: - count += int(form['items requested'].value) -print 'Total orders:', count -#----------------------------- - -# @@PLEAC@@_19.14 -# @@INCOMPLETE@@ -# @@INCOMPLETE@@ - -# @@PLEAC@@_20.1 -#----------------------------- -import urllib -content = urllib.urlopen(url).read() - -try: - import urllib - content = urllib.urlopen(url).read() -except IOError: - print "could not get %s" % url - -#----------------------------- -# download the following standalone program -#!/usr/bin/python -# titlebytes - find the title and size of documents -# -# differences to perl -# -# * no URI::Heuristics -# * perl LWP supports fetching files from local system -# * fetching a title from ftp or file doesnt work in perl either. - -import sys, urllib2, HTMLParser -if len(sys.argv)<=1: - print "usage: %s url" % sys.argv[0] - sys.exit(1) -raw_url = sys.argv[1] - -# python has no equivalent to pearls URI::Heuristics, which -# would do some guessing like : -# -# perl -> http://www.perl.com -# www.oreilly.com -> http://www.oreilly.com -# ftp.funet.fi -> ftp://ftp.funet.fi -# /etc/passwd -> file:/etc/passwd - -# simple but pedantic html parser: tpj.com breaks it. -class html(HTMLParser.HTMLParser): - def __init__(self): - HTMLParser.HTMLParser.__init__(self) - self._data = {} - self._open_tags = [] - def handle_starttag(self, tag, attrs): - self._open_tags.append(tag) - def handle_endtag(self, tag): - if len(self._open_tags)>0: - self._open_tags.pop() - def handle_data(self, data): - if len(self._open_tags)>0: - self._data[self._open_tags[-1]] = data - def __getattr__(self,attr): - if not self._data.has_key(attr): - return "" - return self._data[attr] - -url = raw_url -print "%s =>\n\t" % url, -# TODO fake user agent "Schmozilla/v9.17 Platinum" -# TODO referer "http://wizard.yellowbrick.oz" -# as we only do http httplib would do also -try: - response = urllib2.urlopen(url) -except: - print " %s" % sys.exc_info()[1].reason[1] - sys.exit(1) -# title is not in response -data = response.read() -parser = html() -parser.feed(data) -parser.close() # force processing all data -count = len(data.split("\n")) -bytes = len(data) -print "%s (%d lines, %d bytes)" % (parser.title, - count, - bytes) - -# omly bytes is in response.info() - - -# @@PLEAC@@_20.2 - -# GET method -import httplib -conn = httplib.HTTPConnection('www.perl.com') -conn.request('GET','/cgi-bin/cpan_mod?module=DB_File&readme=1') -r1 = conn.getresponse() -content = r1.read() - -# POST method -import urllib -params = urllib.urlencode({'module': 'DB_File', 'readme': 1}) -content = urllib.urlopen('http://www.perl.com', params).read() - -# fields must be properly escaped -# script.cgi?field1?arg=%22this%20isn%27t%20%3CEASY%3E%22 - -# proxies can be taken from environment, or specified -# as the optional thrid parameter to urlopen. - -# @@PLEAC@@_20.3 -# download the following standalone program -#!/usr/bin/python -# xurl - extract unique, sorted list of links from URL - -from HTMLParser import HTMLParser -import urllib -from sets import Set as set # not needed in 2.4 -class myParser(HTMLParser): - def __init__(self, url): - self.baseUrl = url[:url.rfind('/')] - HTMLParser.__init__(self) - def reset(self): - self.urls = set() - HTMLParser.reset(self) - def handle_starttag(self, tag, attrs): - if tag == 'a': - if attrs[0][0] == 'href': - if attrs[0][1].find(':') == -1: - # we need to add the base URL. - self.urls.add(self.baseUrl + '/' + attrs[0][1]) - else: - self.urls.add(attrs[0][1]) -url = 'http://www.perl.com/CPAN' -p = myParser(url) -s = urllib.urlopen(url) -data = s.read() -p.feed(data) -urllist = p.urls._data.keys() -urllist.sort() -print '\n'.join(urllist) - - - -# @@PLEAC@@_20.4 -# Converting ASCII to HTML - -# download the following standalone program -#!/usr/bin/python -# text2html - trivial html encoding of normal text - -import sys -import re - -# precompile regular expressions -re_quoted = re.compile(r"(?m)^(>.*?)$") -re_url = re.compile(r"<URL:(.*)>") -re_http = re.compile(r"(http:\S+)") -re_strong = re.compile(r"\*(\S+)\*") -re_em = re.compile(r"\b_(\S+)_\b") - -# split paragraphs -for para in open(sys.argv[1]).read().split("\n\n"): - # TODO encode entities: dont encode "<>" but do "&" - if para.startswith(" "): - print "<pre>\n%s\n</pre>" % para - else: - para = re_quoted.sub(r"\1<br />", para) # quoted text - para = re_url.sub(r'<a href="\1">\1</a>', para) # embedded URL - para = re_http.sub(r'<a href="\1">\1</a>', para) # guessed URL - para = re_strong.sub(r"<strong>\1</strong>",para) # this is *bold* here - para = re_em.sub(r"<em>\1</em>",para) # this is _italic_ here - print "<p>\n%s\n</p>" % para # add paragraph tags - - - -#----------------------------- -import sys, re -import htmlentitydefs - -def encode_entities(s): - for k,v in htmlentitydefs.codepoint2name.items(): - if k<256: # no unicodes - s = s.replace(chr(k),"&%s;"%v) - return s - -print "<table>" -text = sys.stdin.read() -text = encode_entities(text) -text = re.sub(r"(\n[ \t]+)"," . ",text) # continuation lines -text = re.sub(r"(?m)^(\S+?:)\s*(.*?)$", - r'<tr><th align="left">\1</th><td>\2</td></tr>', - text); -print text -print "</table>" - -# @@PLEAC@@_20.5 -# Converting HTML to ASCII - -#----------------------------- -import os -ascii = os.popen("lynx -dump " + filename).read() - -#----------------------------- -import formatter -import htmllib - -w = formatter.DumbWriter() -f = formatter.AbstractFormatter(w) -p = htmllib.HTMLParser(f) -p.feed(html) -p.close() - -# Above is a bare minimum to use writer/formatter/parser -# framework of Python. - -# Search Python Cookbook for more details, like writing -# your own writers or formatters. - -# Recipe #52297 has TtyFormatter, formatting underline -# and bold in Terminal. Recipe #135005 has a writer -# accumulating text instead of printing. - -# @@PLEAC@@_20.6 - -import re - -plain_text = re.sub(r"<[^>]*>","",html_text) #WRONG - -# using HTMLParser -import sys, HTMLParser - -class html(HTMLParser.HTMLParser): - def __init__(self): - HTMLParser.HTMLParser.__init__(self) - self._plaintext = "" - self._ignore = False - def handle_starttag(self, tag, attrs): - if tag == "script": - self._ignore = True - def handle_endtag(self, tag): - if tag == "script": - self._ignore = False - def handle_data(self, data): - if len(data)>0 and not self._ignore: - self._plaintext += data - def get_plaintext(self): - return self._plaintext - def error(self,msg): - # ignore all errors - pass - -html_text = open(sys.argv[1]).read() - -parser = html() -parser.feed(html_text) -parser.close() # force processing all data -print parser.get_plaintext() - -title_s = re.search(r"(?i)<title>\s*(.*?)\s*</title>", text) -title = title_s and title_s.groups()[0] or "NO TITLE" - -# download the following standalone program -#!/usr/bin/python -# htitlebytes - get html title from URL -# - -import sys, urllib2, HTMLParser -if len(sys.argv)<=1: - print "usage: %s url ..." % sys.argv[0] - sys.exit(1) - -# simple but pedantic html parser: tpj.com breaks it. -class html(HTMLParser.HTMLParser): - def __init__(self): - HTMLParser.HTMLParser.__init__(self) - self._data = {} - self._open_tags = [] - def handle_starttag(self, tag, attrs): - self._open_tags.append(tag) - def handle_endtag(self, tag): - if len(self._open_tags)>0: - self._open_tags.pop() - def handle_data(self, data): - if len(self._open_tags)>0: - self._data[self._open_tags[-1]] = data - def __getattr__(self,attr): - if not self._data.has_key(attr): - return "" - return self._data[attr] - def error(self,msg): - # ignore all errors - pass - -for url in sys.argv[1:]: - print "%s: " % url, - # TODO fake user agent "Schmozilla/v9.17 Platinum" - # TODO referer "http://wizard.yellowbrick.oz" - # as we only do http httplib would do also - try: - response = urllib2.urlopen(url) - except: - print " %s" % sys.exc_info()[1] - sys.exit(1) - # title is not in response - parser = html() - parser.feed(response.read()) - parser.close() # force processing all data - print parser.title - - - -# @@PLEAC@@_20.7 -# download the following standalone program -#!/usr/bin/python -# churl - check urls - -import sys - -# head request -import urllib -def valid(url): - try: - conn = urllib.urlopen(url) - return 1 - except: - return 0 - -# parser class as in xurl -from HTMLParser import HTMLParser -from sets import Set as set # not needed in 2.4 -class myParser(HTMLParser): - def __init__(self, url): - self.baseUrl = url[:url.rfind('/')] - HTMLParser.__init__(self) - def reset(self): - self.urls = set() - HTMLParser.reset(self) - def handle_starttag(self, tag, attrs): - if tag == 'a': - if attrs[0][0] == 'href': - if attrs[0][1].find(':') == -1: - # we need to add the base URL. - self.urls.add(self.baseUrl + '/' + attrs[0][1]) - else: - self.urls.add(attrs[0][1]) - -if len(sys.argv)<=1: - print "usage: %s <start_url>" % (sys.argv[0]) - sys.exit(1) - -base_url = sys.argv[1] -print base_url+":" -p = myParser(base_url) -s = urllib.urlopen(base_url) -data = s.read() -p.feed(data) -for link in p.urls._data.keys(): - state = "UNKNOWN URL" - if link.startswith("http:"): - state = "BAD" - if valid(link): - state = "OK" - print " %s: %s" % (link, state) - - - -# @@PLEAC@@_20.8 -# download the following standalone program -#!/usr/bin/python -# surl - sort URLs by their last modification date - -import urllib -import time -import sys - -Date = {} -while 1: - # we only read from stdin not from argv. - ln = sys.stdin.readline() - if not ln: - break - ln = ln.strip() - try: - u = urllib.urlopen(ln) - date = time.mktime(u.info().getdate("date")) - if not Date.has_key(date): - Date[date] = [] - Date[date].append(ln) - except: - sys.stderr.write("%s: %s!\n" % (ln, sys.exc_info()[1])) - -dates = Date.keys() -dates.sort() # python 2.4 would have sorted -for d in dates: - print "%s %s" % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(d)), - ", ".join(Date[d])) - - -# @@PLEAC@@_20.9 -import re - -def template(filename, fillings): - text = open(filename).read() - def repl(matchobj): - if fillings.has_key(matchobj.group(1)): - return str(fillings[matchobj.group(1)]) - return "" - # replace quoted words with value from fillings dictionary - text = re.sub("%%(.+?)%%", repl, text) - return text - -fields = { "username":"peter", "count":"23", "total": "1234"} -print template("/home/httpd/templates/simple.template", fields) - -# download the following standalone program -#!/usr/bin/python -# userrep1 - report duration of user logins using SQL database - -import MySQLdb -import cgi -import re -import sys - -def template(filename, fillings): - text = open(filename).read() - def repl(matchobj): - if fillings.has_key(matchobj.group(1)): - return str(fillings[matchobj.group(1)]) - return "" - # replace quoted words with value from fillings dictionary - text = re.sub("%%(.+?)%%", repl, text) - return text - -fields = cgi.FieldStorage() -if not fields.has_key("user"): - print "Content-Type: text/plain\n" - print "No username" - sys.exit(1) - -def get_userdata(username): - db = MySQLdb.connect(passwd="",db="connections", user="bert") - db.query("select count(duration) as count," - +" sum(duration) as total from logins" - +" where username='%s'" % username) - res = db.store_result().fetch_row(maxrows=1,how=1) - res[0]["username"] = username - db.close() - return res[0] - -print "Content-Type: text/html\n" - -print template("report.tpl", get_userdata(fields["user"].value)) - -# @@INCOMPLETE@@ - -# @@PLEAC@@_20.10 -# @@INCOMPLETE@@ -# @@INCOMPLETE@@ - -# @@PLEAC@@_20.11 -# @@INCOMPLETE@@ -# @@INCOMPLETE@@ - -# @@PLEAC@@_20.12 - -# sample data, use ``LOGFILE = open(sys.argv[1])`` in real life -LOGFILE = [ - '127.0.0.1 - - [04/Sep/2005:20:50:31 +0200] "GET /bus HTTP/1.1" 301 303\n', - '127.0.0.1 - - [04/Sep/2005:20:50:31 +0200] "GET /bus HTTP/1.1" 301 303 "-" "Opera/8.02 (X11; Linux i686; U; en)"\n', - '192.168.0.1 - - [04/Sep/2005:20:50:36 +0200] "GET /bus/libjs/layersmenu-library.js HTTP/1.1" 200 6228\n', - '192.168.0.1 - - [04/Sep/2005:20:50:36 +0200] "GET /bus/libjs/layersmenu-library.js HTTP/1.1" 200 6228 "http://localhost/bus/" "Opera/8.02 (X11; Linux i686; U; en)"\n', - ] - -import re - -# similar too perl version. -web_server_log_re = re.compile(r'^(\S+) (\S+) (\S+) \[([^:]+):(\d+:\d+:\d+) ([^\]]+)\] "(\S+) (.*?) (\S+)" (\S+) (\S+)$') - -# with group naming. -split_re = re.compile(r'''(?x) # allow nicer formatting (but requires escaping blanks) - ^(?P<client>\S+)\s - (?P<identuser>\S+)\s - (?P<authuser>\S+)\s - \[ - (?P<date>[^:]+): - (?P<time>[\d:]+)\s - (?P<tz>[^\]]+) - \]\s - " - (?P<method>\S+)\s - (?P<url>.*?)\s - (?P<protocol>\S+) - "\s - (?P<status>\S+)\s - (?P<bytes>\S+) - (?: - \s - " - (?P<referrer>[^"]+) - "\s - " - (?P<agent>[^"]+) - " - )?''') -for line in LOGFILE: - f = split_re.match(line) - if f: - print "agent = %s" % f.groupdict()['agent'] - -# @@PLEAC@@_20.13 -# @@INCOMPLETE@@ -# @@INCOMPLETE@@ - -# @@PLEAC@@_20.14 -# @@INCOMPLETE@@ -# @@INCOMPLETE@@ - |