Python (Dive Into Python) - Documentation & HelpDive Into Python HTML HTML (single file) CHM XML...

Preview:

Citation preview

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

DiveIntoPython Python

DiveIntoPython Updated2004520

DiveIntoPythonHTMLHTML(singlefile)CHMXML(DocBook)Buildscripts()

DiveIntoPython?? CD-ROM? GNUFreeDocumentationLicense,GeneralPublicLicense, FDL GPL

©2000,2001,2002,2003,2004 MarkPilgrim

DiveIntoAccessibility

DiveIntoOSX

DiveIntoGreasemonkey

diveintomark

: >DiveIntoPython>Python >WindowsPython <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

1.2.Windows PythonWindows, Python

ActiveStateWindows Python ActivePython, Python;Python IDE PythonWindows,Windows APIs,Windows

ActivePython, ActivePython Python IDE,,ActiveState Python PythonPython

Python“ ”Python, Python

1.1.1: ActivePython

ActivePython:

1. http://www.activestate.com/Products/ActivePython/ ActivePython

2. Windows95,Windows98WindowsME, ActivePythonWindowsInstaller2.0

3. ActivePython-2.2.2-224-win32-ix86.msi

4.

5. ,,,,14M

6. ,, Start->Programs->ActiveStateActivePython2.2->PythonWinIDE:

PythonWin2.2.2(#37,Nov262002,10:24:37)[MSC32bit(Intel)]onwin32.

PortionsCopyright1994-2001MarkHammond(mhammond@skippinet.com.au)-

see'Help/AboutPythonWin'forfurthercopyrightinformation.

>>>

1.2.2: Python.org Python

1. http://www.python.org/ftp/python/ PythonWindows, .exe

2. Python-2.xxx.yyy.exe Python

3.

4. ,HTMLHelp,( Tools/),/( Lib/test/)

5. ,, AdvancedOptions, Non-AdminInstall

6. ,, Start->Programs->Python2.3->IDLE(PythonGUI):

Python2.3.2(#49,Oct22003,20:02:00)[MSCv.120032bit(Intel)]onwin32

Type"copyright","credits"or"license()"formoreinformation.

****************************************************************

PersonalfirewallsoftwaremaywarnabouttheconnectionIDLE

makestoitssubprocessusingthiscomputer'sinternalloopback

interface.Thisconnectionisnotvisibleonanyexternal

interfaceandnodataissenttoorreceivedfromtheInternet.

****************************************************************

IDLE1.0

>>>

<<Python 123456789 MacOSXPython>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>Python >MacOSXPython <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

1.3.MacOSX Python MacOSX, Python:

MacOSX10.2 Python,, XML, XML,

Shell

1.3. MacOSX Python

Python:

1. /Applications

2. Utilities

3. Terminal

4. python

:

WelcometoDarwin!

[localhost:~]you%python

Python2.2(#1,07/14/02,23:25:09)

[GCCApplecpp-precomp6.14]ondarwin

Type"help","copyright","credits",or"license"formoreinformation.

>>>[pressCtrl+Dtogetbacktothecommandprompt]

[localhost:~]you%

1.4. MacOSX Python

Python:

1. http://homepages.cwi.nl/~jack/macpython/download.htmlMacPython-OSX

2. , MacPython-OSX-2.3-1.dmg

3. MacPython-OSX.pkg.

4.

5.

6. ,, /Applications

7. MacPython-2.3

8. PythonIDE Python

MacPythonIDEshellshell, Window->PythonInteractive(Cmd-0).:

Python2.3(#2,Jul302003,11:45:28)

[GCC3.120020420(prerelease)]

Type"copyright","credits"or"license"formoreinformation.

MacPythonIDE1.0.1

>>>

,,,

1.1. Python

[localhost:~]you%python

Python2.2(#1,07/14/02,23:25:09)

[GCCApplecpp-precomp6.14]ondarwin

Type"help","copyright","credits",or"license"formoreinformation.

>>>[pressCtrl+Dtogetbacktothecommandprompt]

[localhost:~]you%/usr/local/bin/python

Python2.3(#2,Jul302003,11:45:28)

[GCC3.120020420(prerelease)]ondarwin

Type"help","copyright","credits",or"license"formoreinformation.

>>>[pressCtrl+Dtogetbacktothecommandprompt]

[localhost:~]you%

<<WindowsPython 123456789 MacOS9Python>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>Python >MacOS9Python <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

1.4.MacOS9 PythonMacOS9 Python,,

MacOS9 Python:

1. http://homepages.cwi.nl/~jack/macpython/download.htmlMacPython23full.bin

2. , MacPython23full.bin StuffitExpander

3. MacPython23full

4.

5. ,, /Applications

6. MacPython-OS92.3

7. PythonIDE Python

MacPythonIDEshellshell, Window->PythonInteractive(Cmd-0).:

Python2.3(#2,Jul302003,11:45:28)

[GCC3.120020420(prerelease)]

Type"copyright","credits"or"license"formoreinformation.

MacPythonIDE1.0.1

>>>

<<MacOSXPython 123456789 RedHatLinuxPython>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>Python >RedHatLinuxPython <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

1.5.RedHatLinux PythonLinux UNIXLinux

http://www.python.org/ftp/python/, rpms/ PythonRPMrpm,:

1.2.RedHatLinux9

localhost:~$su-

Password:[enteryourrootpassword]

[root@localhostroot]#wgethttp://python.org/ftp/python/2.3/rpms/redhat-9/python2.3-2.3-5pydotorg.i386.rpm

Resolvingpython.org...done.

Connectingtopython.org[194.109.137.226]:80...connected.

HTTPrequestsent,awaitingresponse...200OK

Length:7,495,111[application/octet-stream]

...

[root@localhostroot]#rpm-Uvhpython2.3-2.3-5pydotorg.i386.rpm

Preparing...###########################################[100%]

1:python2.3###########################################[100%]

[root@localhostroot]#python

Python2.2.2(#1,Feb242003,19:13:11)

[GCC3.2.220030222(RedHatLinux3.2.2-4)]onlinux2

Type"help","copyright","credits",or"license"formoreinformation.

>>>[pressCtrl+Dtoexit]

[root@localhostroot]#python2.3

Python2.3(#1,Sep122003,10:53:56)

[GCC3.2.220030222(RedHatLinux3.2.2-5)]onlinux2

Type"help","copyright","credits",or"license"formoreinformation.

>>>[pressCtrl+Dtoexit]

[root@localhostroot]#whichpython2.3

/usr/bin/python2.3

python Python——, python2.3 Python #!shell

<<MacOS9Python 123456789 DebianGNU/LinuxPython>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>Python >DebianGNU/LinuxPython <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

1.6.DebianGNU/Linux PythonDebian GNU/Linux, Python apt

1.3.Debian GNU/Linux

localhost:~$su-

Password:[enteryourrootpassword]

localhost:~#apt-getinstallpython

ReadingPackageLists...Done

BuildingDependencyTree...Done

Thefollowingextrapackageswillbeinstalled:

python2.3

Suggestedpackages:

python-tkpython2.3-doc

ThefollowingNEWpackageswillbeinstalled:

pythonpython2.3

0upgraded,2newlyinstalled,0toremoveand3notupgraded.

Needtoget0B/2880kBofarchives.

Afterunpacking9351kBofadditionaldiskspacewillbeused.

Doyouwanttocontinue?[Y/n]Y

Selectingpreviouslydeselectedpackagepython2.3.

(Readingdatabase...22848filesanddirectoriescurrentlyinstalled.)

Unpackingpython2.3(from.../python2.3_2.3.1-1_i386.deb)...

Selectingpreviouslydeselectedpackagepython.

Unpackingpython(from.../python_2.3.1-1_all.deb)...

Settinguppython(2.3.1-1)...

Settinguppython2.3(2.3.1-1)...

Compilingpythonmodulesin/usr/lib/python2.3...

Compilingoptimizedpythonmodulesin/usr/lib/python2.3...

localhost:~#exit

logout

localhost:~$python

Python2.3.1(#2,Sep242003,11:39:14)

[GCC3.3.220030908(Debianprerelease)]onlinux2

Type"help","copyright","credits"or"license"formoreinformation.

>>>[pressCtrl+Dtoexit]

<<RedHatLinuxPython 123456789 Python>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>Python >Python <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

1.7. Python, http://www.python.org/ftp/python/ Python, .tgz,configure,make,makeinstall

1.4.

localhost:~$su-

Password:[enteryourrootpassword]

localhost:~#wgethttp://www.python.org/ftp/python/2.3/Python-2.3.tgz

Resolvingwww.python.org...done.

Connectingtowww.python.org[194.109.137.226]:80...connected.

HTTPrequestsent,awaitingresponse...200OK

Length:8,436,880[application/x-tar]

...

localhost:~#tarxfzPython-2.3.tgz

localhost:~#cdPython-2.3

localhost:~/Python-2.3#./configure

checkingMACHDEP...linux2

checkingEXTRAPLATDIR...

checkingfor--without-gcc...no

...

localhost:~/Python-2.3#make

gcc-pthread-c-fno-strict-aliasing-DNDEBUG-g-O3-Wall-Wstrict-prototypes

-I.-I./Include-DPy_BUILD_CORE-oModules/python.oModules/python.c

gcc-pthread-c-fno-strict-aliasing-DNDEBUG-g-O3-Wall-Wstrict-prototypes

-I.-I./Include-DPy_BUILD_CORE-oParser/acceler.oParser/acceler.c

gcc-pthread-c-fno-strict-aliasing-DNDEBUG-g-O3-Wall-Wstrict-prototypes

-I.-I./Include-DPy_BUILD_CORE-oParser/grammar1.oParser/grammar1.c

...

localhost:~/Python-2.3#makeinstall

/usr/bin/install-cpython/usr/local/bin/python2.3

...

localhost:~/Python-2.3#exit

logout

localhost:~$whichpython

/usr/local/bin/python

localhost:~$python

Python2.3.1(#2,Sep242003,11:39:14)

[GCC3.3.220030908(Debianprerelease)]onlinux2

Type"help","copyright","credits"or"license"formoreinformation.

>>>[pressCtrl+Dtogetbacktothecommandprompt]

localhost:~$

<<DebianGNU/LinuxPython 123456789 PythonShell>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>Python >PythonShell <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

1.8. PythonShell Python,shell

Python,,,shell, Pythonshell

Pythonshell,:

1.5.Shell

>>>1+1

2

>>>print'helloworld'

helloworld

>>>x=1

>>>y=2

>>>x+y

3

Pythonshell Python,shell Python,print,shellSheel,

<<Python 123456789 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>Python > <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

1.9. Python

, Python, Python

, Python

<<PythonShell 123456789 Python>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>Python > <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

2.2.2.2.1.Python

Python, C++ Pascal interface/implementation,:

defbuildConnectionString(params):

, def,,,()

, Python, Python return,, None(Python)

VisualBasic,() function,() sub Python,( None), def

, Python, params Python,

Java,C++, Python, Python

2.2.1.Python

Python:

Java C

, VBScript Python,

Java Python,,

, VBScript VBScript, '12' 3'123', 123,

Python (), (,)

<<Python 123456 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>Python > <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

2.3. docstring() Python

2.2. buildConnectionString docstring

defbuildConnectionString(params):

"""Buildaconnectionstringfromadictionaryofparameters.

Returnsstring."""

,, docstring

, Perl qq/.../

docstring, docstring,(,) Python docstring

PythonIDE docstring,, docstring, docstring

PEP257 docstringPythonStyleGuide docstring

PythonTutorial docstring

<< 123456 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>Python > <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

2.4.2.4.1.2.4.2.

, Python,

Python,

PythonIDE:

2.3. buildConnectionString docstring

>>>importodbchelper

>>>params={"server":"mpilgrim","database":"master","uid":"sa",

>>>printodbchelper.buildConnectionString(params)

server=mpilgrim;uid=sa;database=master;pwd=secret

>>>printodbchelper.buildConnectionString.__doc__

Buildaconnectionstringfromadictionary

Returnsstring.

odbchelper, Python ( 4 Python),,, buildConnectionString,odbchelper.buildConnectionString Java, __doc__

Python import Perl require import Python, module.function require Perl,module::function

2.4.1.

,, Python, sys.path

)

2.4.

>>>importsys

>>>sys.path

['','/usr/local/lib/python2.2','/usr/local/lib/python2.2/plat-linux2',

'/usr/local/lib/python2.2/lib-dynload','/usr/local/lib/python2.2/site-packages',

'/usr/local/lib/python2.2/site-packages/PIL','/usr/local/lib/python2.2/site-packages/piddle']

>>>sys

<module'sys'(built-in)>

>>>sys.path.append('/my/new/path')

sys,sys.path(,, Python,) Python() .py,, .py, sys,"", Python, Python, Python( sys C), sys.path, Python,,( 3 appendlist)

2.4.2.

Python, __doc__, docstring sys,

, “ ”, ),( 5 )( 4 )

,, Python ,

: >DiveIntoPython>Python > <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

2.5.Python begin end,, (

2.5. buildConnectionString

defbuildConnectionString(params):

"""Buildaconnectionstringfromadictionaryofparameters.

Returnsstring."""

return";".join(["%s=%s"%(k,v)fork,vinparams.items()])

"" if for while,,,,,( docstring)44,

2.6“if” if

2.6.if

deffib(n):

print'n=',n

ifn>1:

returnn*fib(n-1)

else:

print'endoftheline'

return1

fib, n

Python, print print,,(),,() 5 fib,"n=5"

if iftrue,, else if else, else,

Fortran,, Python, Python

Python, C++ Java,

PythonReferenceManual,PythonStyleGuide

<< 123456 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>Python > <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

2.6. Python

if__name__=="__main__":

,, if , if,

C, Python ==, = C, Python,

if, __name__ __name__ import, __name__, __name__

>>>importodbchelper

>>>odbchelper.__name__

'odbchelper'

,, if, __name__ __main__,,

MacPython, if__name__ ,,__main__

PythonReferenceManual

<< 123456 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>>List <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

3.2.List3.2.1.List3.2.2.list3.2.3.list3.2.4.list3.2.5.list

List Pythonlist VisualBasic Powerbuilder,Pythonlist

Pythonlist Perl Perl, @ Python,, Python

Pythonlist Java(, Pythonlist Java) ArrayList,,

3.2.1.List

3.6.List

>>>li=["a","b","mpilgrim","z","example"]

>>>li

['a','b','mpilgrim','z','example']

>>>li[0]

'a'

>>>li[4]

'example'

5listList

List0listli[0]

5list li[4],0

3.7.list

>>>li

['a','b','mpilgrim','z','example']

>>>li[-1]

'example'

>>>li[-3]

'mpilgrim'

listlist li[-1]

,: li[-n]==li[len(li)-n]list, li[-3]==li[5-

3]==li[2]

3.8.list(slice)

>>>li

['a','b','mpilgrim','z','example']

>>>li[1:3]

['b','mpilgrim']

>>>li[1:-1]

['b','mpilgrim','z']

>>>li[0:3]

['a','b','mpilgrim']

2list,“ slice”list,listslice( li[1]),slice( li[3])slice,slice,list,slice,slice

List0, li[0:3]list3, li[0], li[3]

3.9.Slice

>>>li

['a','b','mpilgrim','z','example']

>>>li[:3]

['a','b','mpilgrim']

>>>li[3:]

['z','example']

>>>li[:]

['a','b','mpilgrim','z','example']

0,,0 li[:3] 3.8“list(slice)” li[0:3],list, li[3:] li[3:5],list55list, li[:3]3, li[3:]2, li[:n]

n, li[n:],list,list lilist,list, li li[:]list

3.2.2.list

3.10.list

>>>li

['a','b','mpilgrim','z','example']

>>>li.append("new")

>>>li

['a','b','mpilgrim','z','example','new']

>>>li.insert(2,"new")

>>>li

['a','b','new','mpilgrim','z','example','new']

>>>li.extend(["two","elements"])

>>>li

['a','b','new','mpilgrim','z','example','new','two','elements']

appendlist

insertlist,list, 'new', li[2]

li[6]

extendlist extend,list,list

3.11.extend() append()

>>>li=['a','b','c']

>>>li.extend(['d','e','f'])

>>>li

['a','b','c','d','e','f']

>>>len(li)

6

>>>li[-1]

'f'

>>>li=['a','b','c']

>>>li.append(['d','e','f'])

>>>li

['a','b','c',['d','e','f']]

>>>len(li)

4

>>>li[-1]

['d','e','f']

Lists extend append, extend,list,listlistlist3( 'a','b' 'c'),3( 'd','e' 'f')list,list6, append,,list3list44? extend, append

3.2.3.list

3.12.list

>>>li

['a','b','new','mpilgrim','z','example','new','two','elements']

>>>li.index("example")

5

>>>li.index("new")

2

>>>li.index("c")

Traceback(innermostlast):

File"<interactiveinput>",line1,in?

ValueError:list.index(x):xnotinlist

>>>"c"inli

False

indexlistindexlist 'new'list, li[2] li[6],index, 2

list, Python,,,,list, in,, True, False

2.2.1, Python, Python( if),:

0false;true( "")false;truelist( [])false;listtruetuple( ())false;tupletruedictionary( {})false;dictionarytrue

Python2.2.1,, True False Python

3.2.4.list

3.13.list

>>>li

['a','b','new','mpilgrim','z','example','new','two','elements']

>>>li.remove("z")

>>>li

['a','b','new','mpilgrim','example','new','two','elements']

>>>li.remove("new")

>>>li

['a','b','mpilgrim','example','new','two','elements']

>>>li.remove("c")

Traceback(innermostlast):

File"<interactiveinput>",line1,in?

ValueError:list.remove(x):xnotinlist

>>>li.pop()

'elements'

>>>li

['a','b','mpilgrim','example','new','two']

removelistremove, 'new'list, li.remove("new") 'new'

list, Python indexpop:list,, li[-1],listli.remove(value),list

3.2.5.list

3.14.List

>>>li=['a','b','mpilgrim']

>>>li=li+['example','new']

>>>li

['a','b','mpilgrim','example','new']

>>>li+=['two']

>>>li

['a','b','mpilgrim','example','new','two']

>>>li=[1,2]*3

>>>li

[1,2,1,2,1,2]

Lists + list=list+otherlistlist.extend(otherlist) +()list, extendlist,list, extendPython += li+=['two'] li.extend(['two']) +=list,,( 5*list li=[1,2]*3 li=[1,2]+[1,2]+[1,2],list

HowtoThinkLikeaComputerScientistlist, listPythonTutorial listPythonKnowledgeBase list listPythonLibraryReference list

<< 12345678 Tuple>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>>Tuple <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

3.3.TupleTuplelisttuple

3.15.tuple

>>>t=("a","b","mpilgrim","z","example")

>>>t

('a','b','mpilgrim','z','example')

>>>t[0]

'a'

>>>t[-1]

'example'

>>>t[1:3]

('b','mpilgrim')

tuplelist,TuplelistTupleslist0,tuple t[0]

listtuplelist(slice)list,listtuple,tuple

3.16.Tuple

>>>t

('a','b','mpilgrim','z','example')

>>>t.append("new")

Traceback(innermostlast):

File"<interactiveinput>",line1,in?

AttributeError:'tuple'objecthasnoattribute'append'

>>>t.remove("z")

Traceback(innermostlast):

File"<interactiveinput>",line1,in?

AttributeError:'tuple'objecthasnoattribute'remove'

>>>t.index("example")

Traceback(innermostlast):

File"<interactiveinput>",line1,in?

AttributeError:'tuple'objecthasnoattribute'index'

>>>"z"int

True

tupleTuple append extend

tupleTuple remove pop

tupleTuple index, intuple

tuple

Tuplelist,,tuplelist“ ”,tuplelist assert,,tuplelist() dictionarykeys,“ ”? Tuples Tuplesdictionarykey,list,DictionarykeyTuple,listtuple,,dictionarykey,dictionarytupledictionarykeyTuples,

Tuplelist, tuplelist,tuplelist, tuplelist, listtuple

: >DiveIntoPython>> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

3.4.3.4.1.3.4.2.

dictionary,tuple,list(,), 2

Python,,

3.17. myParams

if__name__=="__main__":

myParams={"server":"mpilgrim",\

"database":"master",\

"uid":"sa",\

"pwd":"secret"\

}

if,

,,(“ \”)

(“ \”),, Python PythonIDE,,

,,( dictionary )(“ \”),,,

, myParams, VBScript optionexplicit, VBScript, Python,

3.4.1.

3.18.

>>>x

Traceback(innermostlast):

File"<interactiveinput>",line1,in?

NameError:Thereisnovariablenamed'x'

>>>x=1

>>>x

1

Python

3.4.2.

Python“”

3.19.

>>>v=('a','b','e')

>>>(x,y,z)=v

>>>x

'a'

>>>y

'b'

>>>z

'e'

vtuple, (x,y,z)tupletupletuple, v

C, enum,, Python, range

3.20.

>>>range(7)

[0,1,2,3,4,5,6]

>>>(MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY,SUNDAY)=range(7)

>>>MONDAY

0

>>>TUESDAY

1

>>>SUNDAY

6

rangelist,0list,,(,printrange.__doc__)MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY SUNDAY( calendar, UNIX cal calendar): MONDAY 0,TUESDAY 1,

,tupletuple, Python, os, 6

PythonReferenceManualHowtoThinkLikeaComputerScientist

<<Tuple 12345678 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

3.5.Python, %s

Python, C sprintf

3.21.

>>>k="uid"

>>>v="sa"

>>>"%s=%s"%(k,v)

'uid=sa'

%s k %s v(,)

(k,v)tuple

,,

3.22.

>>>uid="sa"

>>>pwd="secret"

>>>printpwd+"isnotagoodpasswordfor"+uid

secretisnotagoodpasswordforsa

>>>print"%sisnotagoodpasswordfor%s"%(pwd,uid)

secretisnotagoodpasswordforsa

>>>userCount=6

>>>print"Usersconnected:%d"%(userCount,)

Usersconnected:6

>>>print"Usersconnected:"+userCount

Traceback(innermostlast):

File"<interactiveinput>",line1,in?

TypeError:cannotconcatenate'str'and'int'objects

+,(userCount,)tuple,,tuple,,list,tupledictionary,,tuple,tuple userCount %s %d,

printf C, Python,

3.23.

>>>print"Today'sstockprice:%f"%50.4625

50.462500

>>>print"Today'sstockprice:%.2f"%50.4625

50.46

>>>print"Changesinceyesterday:%+.2f"%1.5

+1.50

%f,6".2" %f2 +".2",2

PythonLibraryReferenceEffectiveAWKProgramming , ,0

<< 12345678 list>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>>list <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

3.6.listPythonlist,,list,listlist

3.24.List

>>>li=[1,9,8,4]

>>>[elem*2foreleminli]

[2,18,16,8]

>>>li

[1,9,8,4]

>>>li=[elem*2foreleminli]

>>>li

[2,18,16,8]

, lilist Python li, elem, Pythonelem*2,list,listlistlist Pythonlist,list, Python

2 buildConnectionStringlist:

["%s=%s"%(k,v)fork,vinparams.items()]

,dictionary params itemsdictionarytuplelist

3.25.keys,values items

>>>params={"server":"mpilgrim","database":"master","uid":"sa",

>>>params.keys()

['server','uid','database','pwd']

>>>params.values()

['mpilgrim','sa','master','secret']

>>>params.items()

[('server','mpilgrim'),('uid','sa'),('database','master'),('pwd','secret')]

Dictionary keyslistlistdictionary(,dictionary),listvalueslistlist keyslist, n,params.values()[n]==params[params.keys()[n]]items (key,value)tuplelistlistdictionary

buildConnectionStringlist, params.items(),listlistparams.items(),listdictionary params

3.26.buildConnectionStringlist

>>>params={"server":"mpilgrim","database":"master","uid":"sa",

>>>params.items()

[('server','mpilgrim'),('uid','sa'),('database','master'),('pwd','secret')]

>>>[kfork,vinparams.items()]

['server','uid','database','pwd']

>>>[vfork,vinparams.items()]

['mpilgrim','sa','master','secret']

>>>["%s=%s"%(k,v)fork,vinparams.items()]

['server=mpilgrim','uid=sa','database=master','pwd=secret']

list params.items() params.items() ('server',

'mpilgrim'),list, k 'server',v 'mpilgrim',list v, k,list params.keys(), k,list params.values() ,dictionarykey-valuelist list

PythonTutoriallist mapPythonTutorial listlist

<< 12345678 list>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>>list <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

3.7.list3.7.1.

key=valuekey-valuelist,list, join

buildConnectionStringlist:

return";".join(["%s=%s"%(k,v)fork,vinparams.items()])

,, ,, ";", join

, joinlist,

joinlist;list

3.27.odbchelper.py

>>>params={"server":"mpilgrim","database":"master","uid":"sa",

>>>["%s=%s"%(k,v)fork,vinparams.items()]

['server=mpilgrim','uid=sa','database=master','pwd=secret']

>>>";".join(["%s=%s"%(k,v)fork,vinparams.items()])

'server=mpilgrim;uid=sa;database=master;pwd=secret'

odbchelper,,

list, split

3.28.

>>>li=['server=mpilgrim','uid=sa','database=master','pwd=secret'

>>>s=";".join(li)

>>>s

'server=mpilgrim;uid=sa;database=master;pwd=secret'

>>>s.split(";")

['server=mpilgrim','uid=sa','database=master','pwd=secret']

>>>s.split(";",1)

['server=mpilgrim','uid=sa;database=master;pwd=secret']

split join,list ,(“ ;”),listsplit,(“ ,... ”,)

anystring.split(delimiter,1),,(list)(list),

PythonKnowledgeBase ,PythonLibraryReferencePythonLibraryReference stringTheWholePythonFAQ joinlist

3.7.1.

Python, joinlist,, join Python1.6, string,,, lower,upper split Pythonjoin,list, string()string.join

<<list 12345678 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

3.8. odbchelper.py

defbuildConnectionString(params):

"""Buildaconnectionstringfromadictionaryofparameters.

Returnsstring."""

return";".join(["%s=%s"%(k,v)fork,vinparams.items()])

if__name__=="__main__":

myParams={"server":"mpilgrim",\

"database":"master",\

"uid":"sa",\

"pwd":"secret"\

}

printbuildConnectionString(myParams)

odbchelper.py:

server=mpilgrim;uid=sa;database=master;pwd=secret

,:

PythonIDE Python IDE, docstring, dictionary,tuple list,:,list,dictionary,

list list listlistlist

<<list 12345678 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

4.2.Python SQLServerTransact/SQL

info

definfo(object,spacing=10,collapse=1):

spacing collapse object info spacing10collapse 1 info collapse 1

collapse spacing spacing Python

4.4.info

info(odbchelper)

info(odbchelper,12)

info(odbchelper,collapse=0)

info(spacing=15,object=odbchelper)

spacing 10collapse 1

collapse 1

collapse spacing10

( object),

“ ” Python“ ”

: >DiveIntoPython>>typestrdir <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

4.3. typestrdir

4.3.1.type4.3.2.str4.3.3.

Python VisualBasic

4.3.1.type

type types

4.5.type

>>>type(1)

<type'int'>

>>>li=[]

>>>type(li)

<type'list'>

>>>importodbchelper

>>>type(odbchelper)

<type'module'>

>>>importtypes

>>>type(odbchelper)==types.ModuleType

True

type----typetypetype types info

4.3.2.str

str

4.6.str

>>>str(1)

'1'

>>>horsemen=['war','pestilence','famine']

>>>horsemen

['war','pestilence','famine']

>>>horsemen.append('Powerbuilder')

>>>str(horsemen)

"['war','pestilence','famine','Powerbuilder']"

>>>str(odbchelper)

"<module'odbchelper'from'c:\\docbook\\dip\\py\\odbchelper.py'>"

>>>str(None)

'None'

str strstrstr NoneNone Pythonnull 'None' info

info dir dir……

4.7.dir

>>>li=[]

>>>dir(li)

['append','count','extend','index','insert',

'pop','remove','reverse','sort']

>>>d={}

>>>dir(d)

['clear','copy','get','has_key','items','keys','setdefault','update','values']

>>>importodbchelper

>>>dir(odbchelper)

['__builtins__','__doc__','__file__','__name__','buildConnectionString']

li dir(li)d dir(d) keys

odbchelper dir(odbchelper)__name____doc__, odbchelper 2buildConnectionString

callable True False

4.8.callable

>>>importstring

>>>string.punctuation

'!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'

>>>string.join

<functionjoinat00C55A7C>

>>>callable(string.punctuation)

False

>>>callable(string.join)

True

>>>printstring.join.__doc__

join(list[,sep])->string

Returnastringcomposedofthewordsinlist,with

interveningoccurrencesofsep.Thedefaultseparatorisa

singlespace.

(joinfieldsandjoinaresynonymous)

string join string.punctuation

string.joinstring.punctuationstring.join docstring callable

4.3.3.

typestrdir Python __builtin__ Python from

__builtin__import*“ ”

__builtin__ Python info AttributeError

4.9.

>>>fromapihelperimportinfo

>>>import__builtin__

>>>info(__builtin__,20)

ArithmeticErrorBaseclassforarithmeticerrors.

AssertionErrorAssertionfailed.

AttributeErrorAttributenotfound.

EOFErrorReadbeyondendoffile.

EnvironmentErrorBaseclassforI/Orelatederrors.

ExceptionCommonbaseclassforallexceptions.

FloatingPointErrorFloatingpointoperationfailed.

IOErrorI/Ooperationfailed.

[...snip...]

: >DiveIntoPython>>getattr <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

4.4. getattr

4.4.1.getattr4.4.2.getattr

Python getattr

4.10.getattr

>>>li=["Larry","Curly"]

>>>li.pop

<built-inmethodpopoflistobjectat010DF884>

>>>getattr(li,"pop")

<built-inmethodpopoflistobjectat010DF884>

>>>getattr(li,"append")("Moe")

>>>li

["Larry","Curly","Moe"]

>>>getattr({},"clear")

<built-inmethodclearofdictionaryobjectat00F113D4>

>>>getattr((),"pop")

Traceback(innermostlast):

File"<interactiveinput>",line1,in?

AttributeError:'tuple'objecthasnoattribute'pop'

pop pop pop li.pop()

pop getattr getattrlistpop

getattr li.append("Moe")getattr

getattr getattr

4.4.1. getattr

getattr

4.11.apihelper.py getattr

>>>importodbchelper

>>>odbchelper.buildConnectionString

<functionbuildConnectionStringat00D18DD4>

>>>getattr(odbchelper,"buildConnectionString")

<functionbuildConnectionStringat00D18DD4>

>>>object=odbchelper

>>>method="buildConnectionString"

>>>getattr(object,method)

<functionbuildConnectionStringat00D18DD4>

>>>type(getattr(object,method))

<type'function'>

>>>importtypes

>>>type(getattr(object,method))==types.FunctionType

True

>>>callable(getattr(object,method))

True

odbchelper buildConnectionString 2 Python

getattr getattr(object,"attribute") object.attribute

object attribute info object method

method type method

4.4.2.getattr

getattr

HTMLXML statsout output_htmloutput_xmloutput_text

4.12. getattr

importstatsout

defoutput(data,format="text"):

output_function=getattr(statsout,"output_%s"%format)

returnoutput_function(data)

output data format format text format"output_" statsout statsoutoutput_pdf“pdf” format output

output_function statsout

Bug statsout getattr None

output_function

getattr

4.13.getattr

importstatsout

defoutput(data,format="text"):

output_function=getattr(statsout,"output_%s"%format,statsout.output_text)

returnoutput_function(data)

getattr

getattr

<<typestrdir 123456789 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

4.5.Python3.6“list”

[mapping-expressionforelementinsource-listiffilter-expression

if Python

4.14.

>>>li=["a","mpilgrim","foo","b","c","b","d","d"]

>>>[elemforeleminliiflen(elem)>1]

['mpilgrim','foo']

>>>[elemforeleminliifelem!="b"]

['a','mpilgrim','foo','c','d','d']

>>>[elemforeleminliifli.count(elem)==1]

['a','mpilgrim','foo','c']

Python

b b b

count b d

apihelper.py

methodList=[methodformethodindir(object)ifcallable(getattr(object,method))]

methodList dir(object) object—— if

callablegetattr in object method

getattr(object,method)

object// getattr pop odbchelper buildConnectionString __name__

PythonTutorial

<<getattr 123456789 andor>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>>andor <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

4.6.and or

4.6.1.and-or

Python and or

4.15.and

>>>'a'and'b'

'b'

>>>''and'b'

''

>>>'a'and'b'and'c'

'c'

and 0''[](){}None 5 and and 'a' 'b' 'b'

and '' and 'c'

4.16.or

>>>'a'or'b'

'a'

>>>''or'b'

'b'

>>>''or[]or{}

{}

>>>defsidefx():

...print"insidefx()"

...return1

>>>'a'orsidefx()

'a'

or and or 'a'or '' 'b' 'b'

or or '' [] {} {} or sidefx or 'a''a'

C bool?a:b bool a b Python and or

4.6.1. and-or

4.17.and-or

>>>a="first"

>>>b="second"

>>>1andaorb

'first'

>>>0andaorb

'second'

C bool?a:b and 1and'first''first' 'first'or'second' 'first'

0and'first' False 0or'second' 'second'

Python and-or C bool?a:b a

4.18.and-or

>>>a=""

>>>b="second"

>>>1andaorb

'second'

a Python 1and'' '' ''or'second''second'

and-or boolandaorb a C bool?a:b

and-or a a [a] b [b] a b

4.19. and-or

>>>a=""

>>>b="second"

>>>(1and[a]or[b])[0]

''

[a] a 0 '' [a]

if lambda

PythonCookbook and-or

<< 123456789 lambda>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>>lambda <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

4.7. lambda

4.7.1.lambda

Python lambda Lisp

4.20.lambda

>>>deff(x):

...returnx*2

...

>>>f(3)

6

>>>g=lambdax:x*2

>>>g(3)

6

>>>(lambdax:x*2)(3)

6

lambda return

lambda lambda

lambda lambda lambda

lambda

4.7.1. lambda

apihelper.py lambda

processFunc=collapseand(lambdas:"".join(s.split()))or(

and-or lambda lambda

split

4.21.split

>>>s="thisis\na\ttest"

>>>prints

thisis

a test

>>>prints.split()

['this','is','a','test']

>>>print"".join(s.split())

'thisisatest'

\n \t split split join info doc

string

info lambda split and-or

processFunc=collapseand(lambdas:"".join(s.split()))or(

processFunc collapse collapse processFunc(string) processFunc(string)

VisualBasic collapse ifPython lambda

lambda

PythonKnowledgeBase lambda

: >DiveIntoPython>> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

4.8.

apihelper.py

print"\n".join(["%s%s"%

(method.ljust(spacing),

processFunc(str(getattr(object,method).__doc__)))

formethodinmethodList])

\

formethodinmethodList

methodList object method

4.22. docstring

>>>importodbchelper

>>>object=odbchelper

>>>method='buildConnectionString'

>>>getattr(object,method)

<functionbuildConnectionStringat010D6D74>

>>>printgetattr(object,method).__doc__

Buildaconnectionstringfromadictionaryofparameters.

Returnsstring.

info object methodList method getattr object method

docstring

docstring str str docstring str docstring __doc__ None

4.23. docstring str

>>>>>>deffoo():print2

>>>>>>foo()

2

>>>>>>foo.__doc__

>>>foo.__doc__==None

True

>>>str(foo.__doc__)

'None'

docstring __doc__ None __doc__

IDE __doc__ None __doc__strnull 'None'

SQL ISNULL =NULLnull Python ==

None isNone isNone

processFunc str None processFunc split None None split

processFunc method ljust ljust

4.24.ljust

>>>s='buildConnectionString'

>>>s.ljust(30)

'buildConnectionString'

>>>s.ljust(20)

'buildConnectionString'

ljust info docstring

ljust

ljust processFunc docstring methodList "\n" join

4.25.

>>>li=['a','b','c']

>>>print"\n".join(li)

a

b

c

Python

print"\n".join(["%s%s"%

(method.ljust(spacing),

processFunc(str(getattr(object,method).__doc__)))

formethodinmethodList])

<<lambda 123456789 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

4.9.apihelper.py

definfo(object,spacing=10,collapse=1):

"""Printmethodsanddocstrings.

Takesmodule,class,list,dictionary,orstring."""

methodList=[methodformethodindir(object)ifcallable(getattr(object,method))]

processFunc=collapseand(lambdas:"".join(s.split()))or(

print"\n".join(["%s%s"%

(method.ljust(spacing),

processFunc(str(getattr(object,method).__doc__)))

formethodinmethodList])

if__name__=="__main__":

printinfo.__doc__

apihelper.py

>>>fromapihelperimportinfo

>>>li=[]

>>>info(li)

appendL.append(object)--appendobjecttoend

countL.count(value)->integer--returnnumberofoccurrencesofvalue

extendL.extend(list)--extendlistbyappendinglistelements

indexL.index(value)->integer--returnindexoffirstoccurrenceofvalue

insertL.insert(index,object)--insertobjectbeforeindex

popL.pop([index])->item--removeandreturnitematindex(defaultlast)

removeL.remove(value)--removefirstoccurrenceofvalue

reverseL.reverse()--reverse*INPLACE*

sortL.sort([cmpfunc])--sort*INPLACE*;ifgiven,cmpfunc(x,y)->-1,0,1

str getattr and-or lambda Python

<< 123456789 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>>frommoduleimport <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

5.2. frommoduleimport

Python importmodule2.4“”

frommoduleimport

fromUserDictimportUserDict

importmodule types frommoduleimport*

Python frommoduleimport* Perl usemodule

Python importmodule Perl requiremodule

Python frommoduleimport* Java importmodule.*

Python importmodule Java importmodule

5.2.importmodulevs.frommoduleimport

>>>importtypes

>>>types.FunctionType

<type'function'>

>>>FunctionType

Traceback(innermostlast):

File"<interactiveinput>",line1,in?

NameError:Thereisnovariablenamed'FunctionType'

>>>fromtypesimportFunctionType

>>>FunctionType

<type'function'>

types Python types

FunctionType types types FunctionType FunctionType types

frommoduleimport

frommodule

frommoduleimport

importmodule

Python

frommoduleimport*

eff-bot importmodulevs.frommoduleimportPythonTutorial frommoduleimport*

<< 12345678910 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

5.3.5.3.1.5.3.2.self__init__

Python

Python Python class

5.3. Python

classLoaf:

pass

Loaf EachWordLikeThis

pass Python“ ”

if for

Python pass Java C( {})

C++ Python Python __init__

5.4. FileInfo

fromUserDictimportUserDict

classFileInfo(UserDict):

Python FileInfo UserDict UserDict

UserDict UserList UserString2.2dict,list“”

Python Java extends

Python

5.3.1.

__init__ FileInfo

5.5. FileInfoClass

classFileInfo(UserDict):

"storefilemetadata"

def__init__(self,filename=None):

docstrings__init__ __init__“ init” __init__ __init__ Python

__init__ self __init__ self self

Python__init__ filename None Python

Python self C++ Java thisself Python self

5.6. FileInfo

classFileInfo(UserDict):

"storefilemetadata"

def__init__(self,filename=None):

UserDict.__init__(self)

self["name"]=filename

Powerbuilder“ ” Python

filename name __init__

5.3.2. self __init__

self __init__ self selfPython

Python

__init__ __init__

Python

LearningtoProgramHowtoThinkLikeaComputerScientistPythonTutorialPythonKnowledgeBase

<<frommoduleimport12345678910 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

5.4.5.4.1.

Python __init__

5.7. FileInfo

>>>importfileinfo

>>>f=fileinfo.FileInfo("/music/_singles/kairo.mp3")

>>>f.__class__

<classfileinfo.FileInfoat010EC204>

>>>f.__doc__

'storefilemetadata'

>>>f

{'name':'/music/_singles/kairo.mp3'}

FileInfo fileinfo f

/music/_singles/kairo.mp3 FileInfo __init__filename __class__ Java Class getNamegetSuperclass Python __class__

__bases__ docstring docstring

__init__ filename self["name"] __init____init__

Python C++ Java new

5.4.1.

Python

5.8.

>>>defleakmem():

...f=fileinfo.FileInfo('/music/_singles/kairo.mp3')

...

>>>foriinrange(100):

...leakmem()

leakmem FileInfo f f f FileInfo f Python leakmem Python leakmem FileInfo

“ ” Python FileInfo f f 0 Python

Python Python Python Python2.0“ ”

Python Python

PythonLibraryReference __class__PythonLibraryReference gc Python

<< 12345678910 UserDict:>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>>UserDict: <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

5.5. UserDict:

FileInfo UserDict UserDict FileInfoPython .py Python lib

Windows ActivePythonIDE File->Locate...(Ctrl-L)

5.9. UserDict

classUserDict:

def__init__(self,dict=None):

self.data={}

ifdictisnotNone:self.update(dict)

UserDict FileInfo __init__FileInfoPython Java Powerbuilder“ ” C++“ ”UserDict data instance.data self __init__update update if C++

Java Powerbuilder PL/SQL Python __init__ __init__

__init__ __init__ __init__

PythonGuido“ C++Python”

__init__ AttributeError

5.10.UserDict

defclear(self):self.data.clear()

defcopy(self):

ifself.__class__isUserDict:

returnUserDict(self.data)

importcopy

returncopy.copy(self)

defkeys(self):returnself.data.keys()

defitems(self):returnself.data.items()

defvalues(self):returnself.data.values()

clear clear selfPython( data) copy-self

__class__ self UserDict UserDict UserDict self.data UserDict importcopy

self.__class__ UserDict self UserDictFileInfo UserDict copy Python self.data

Python2.2 Python UserString

UserList UserDict UserDict Python2.2 dict fileinfo_fromdict.py

Python dict UserDict

5.11. dict

classFileInfo(dict):

"storefilemetadata"

def__init__(self,filename=None):

self["name"]=filename

UserDict dict UserDict.UserDict dict

UserDict __init__ dict

PythonLibraryReference UserDict copy

<< 12345678910 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

5.6.5.6.1.

Python Python

5.6.1.

5.12.__getitem__

def__getitem__(self,key):returnself.data[key]

>>>f=fileinfo.FileInfo("/music/_singles/kairo.mp3")

>>>f

{'name':'/music/_singles/kairo.mp3'}

>>>f.__getitem__("name")

'/music/_singles/kairo.mp3'

>>>f["name"]

'/music/_singles/kairo.mp3'

__getitem__ clearkeys values__getitem__ Python f.__getitem__("name")__getitem__ Python

, Python __getitem__ __setitem__,

5.13.__setitem__

def__setitem__(self,key,item):self.data[key]=item

>>>f

{'name':'/music/_singles/kairo.mp3'}

>>>f.__setitem__("genre",31)

>>>f

{'name':'/music/_singles/kairo.mp3','genre':31}

>>>f["genre"]=32

>>>f

{'name':'/music/_singles/kairo.mp3','genre':32}

__getitem__ __setitem__ self.data__getitem__ Python __setitem__ f __setitem__ f.__setitem__("genre",

32)

__setitem__ Python UserDict __setitem__

__setitem__

MP3FileInfo FileInfo MP3FileInfo name name FileInfo MP3

5.14. MP3FileInfo __setitem__

def__setitem__(self,key,item):

ifkey=="name"anditem:

self.__parse(item)

FileInfo.__setitem__(self,key,item)

__setitem__ Python MP3FileInfo name name __parse MP3FileInfo self__parse self.__parse Python FileInfo __setitem__ Python UserDict __setitem__

self.attribute self.method

5.15. MP3FileInfo name

>>>importfileinfo

>>>mp3file=fileinfo.MP3FileInfo()

>>>mp3file

{'name':None}

>>>mp3file["name"]="/music/_singles/kairo.mp3"

>>>mp3file

{'album':'RaveMix','artist':'***DJMARY-JANE***','genre':31,

'title':'KAIRO****THEBESTGOA','name':'/music/_singles/kairo.mp3',

'year':'2000','comment':'http://mp3.com/DJMARYJANE'}

>>>mp3file["name"]="/music/_singles/sidewinder.mp3"

>>>mp3file

{'album':'','artist':'TheCynicProject','genre':18,'title':'Sidewinder',

'name':'/music/_singles/sidewinder.mp3','year':'2000',

'comment':'http://mp3.com/cynicproject'}

MP3FileInfo __init__ filename MP3FileInfo __init__ Python FileInfo__init__ __init__ UserDict __init__ name filename None mp3file name None

mp3file name MP3FileInfo __setitem__UserDict name self.__parse __parse

album,artist,genre,title,year comment

name Python __setitem____setitem__

self.__parseself.__parse

<<UserDict: 12345678910 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

5.7. __getitem__ __setitem__ Python

UserDict

5.16.UserDict

def__repr__(self):returnrepr(self.data)

def__cmp__(self,dict):

ifisinstance(dict,UserDict):

returncmp(self.data,dict.data)

else:

returncmp(self.data,dict)

def__len__(self):returnlen(self.data)

def__delitem__(self,key):delself.data[key]

__repr__ repr(instance) repr repr

ENTER

__cmp__ == Python__cmp__ == Python __cmp____len__ len(instance) len len __len__ len(instance

__len____delitem__ delinstance[key] del Python __delitem__

Java str1==str2 Python str1isstr2

Java str1.equals(str2) Python str1==

str2 Java Java == JavaPython Java str1==str2 objectidentity Python str1isstr2 Javastr1.equals(str2) Python str1==str2 Java

== Java Python“ ”

“ ” UserDict UserDict

- __setitem__ __getitem__ GetLength __len__

“ GetLength” Python __len__“ ”

Python

PythonReferenceManual

<< 12345678910 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

5.8. Python

5.17.

classMP3FileInfo(FileInfo):

"storeID3v1.0MP3tags"

tagDataMap={"title":(3,33,stripnulls),

"artist":(33,63,stripnulls),

"album":(63,93,stripnulls),

"year":(93,97,stripnulls),

"comment":(97,126,stripnulls),

"genre":(127,128,ord)}

>>>importfileinfo

>>>fileinfo.MP3FileInfo

<classfileinfo.MP3FileInfoat01257FDC>

>>>fileinfo.MP3FileInfo.tagDataMap

{'title':(3,33,<functionstripnullsat0260C8D4>),

'genre':(127,128,<built-infunctionord>),

'artist':(33,63,<functionstripnullsat0260C8D4>),

'year':(93,97,<functionstripnullsat0260C8D4>),

'comment':(97,126,<functionstripnullsat0260C8D4>),

'album':(63,93,<functionstripnullsat0260C8D4>)}

>>>m=fileinfo.MP3FileInfo()

>>>m.tagDataMap

{'title':(3,33,<functionstripnullsat0260C8D4>),

'genre':(127,128,<built-infunctionord>),

'artist':(33,63,<functionstripnullsat0260C8D4>),

'year':(93,97,<functionstripnullsat0260C8D4>),

'comment':(97,126,<functionstripnullsat0260C8D4>),

'album':(63,93,<functionstripnullsat0260C8D4>)}

MP3FileInfotagDataMap

Java Python Python static Python __init__

MP3FileInfo

Python Python None

5.18.

>>>classcounter:

...count=0

...def__init__(self):

...self.__class__.count+=1

...

>>>counter

<class__main__.counterat010EAECC>

>>>counter.count

0

>>>c=counter()

>>>c.count

1

>>>counter.count

1

>>>d=counter()

>>>d.count

2

>>>c.count

2

>>>counter.count

2

count counter__class__ self counter

count __init__ count 1

count

<< 12345678910 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

5.9.Python

Python

Python Python

MP3FileInfo __parse __setitem__ __setitem__ fileinfo

Python __setitem__ __doc__

5.19.

>>>importfileinfo

>>>m=fileinfo.MP3FileInfo()

>>>m.__parse("/music/_singles/kairo.mp3")

Traceback(innermostlast):

File"<interactiveinput>",line1,in?

AttributeError:'MP3FileInfo'instancehasnoattribute'__parse'

Python Python _MP3FileInfo__parse

: >DiveIntoPython>> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

5.10. 12 , getattrWeb

Python,, for

importmodule frommoduleimport

__init__ , UserDict ,

<< 12345678910 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

6.2.6.2.1.6.2.2.6.2.3.I/O6.2.4.

Python open open

6.3.

>>>f=open("/music/_singles/kairo.mp3","rb")

>>>f

<openfile'/music/_singles/kairo.mp3',mode'rb'at010E3988>

>>>f.mode

'rb'

>>>f.name

'/music/_singles/kairo.mp3'

open printopen.__doc__

open mode name

6.2.1.

,,

6.4.

>>>f

<openfile'/music/_singles/kairo.mp3',mode'rb'at010E3988>

>>>f.tell()

0

>>>f.seek(-128,2)

>>>f.tell()

7542909

>>>tagData=f.read(128)

>>>tagData

'TAGKAIRO****THEBESTGOA***DJMARY-JANE***

RaveMix2000http://mp3.com/DJMARYJANE\037'

>>>f.tell()

7543037

tell 0

seek 0 1 2 2 128tellread tagData

tell128128

6.2.2.

,,

6.5.

>>>f

<openfile'/music/_singles/kairo.mp3',mode'rb'at010E3988>

>>>f.closed

False

>>>f.close()

>>>f

<closedfile'/music/_singles/kairo.mp3',mode'rb'at010E3988>

>>>f.closed

True

>>>f.seek(0)

Traceback(innermostlast):

File"<interactiveinput>",line1,in?

ValueError:I/Ooperationonclosedfile

>>>f.tell()

Traceback(innermostlast):

File"<interactiveinput>",line1,in?

ValueError:I/Ooperationonclosedfile

>>>f.read()

Traceback(innermostlast):

File"<interactiveinput>",line1,in?

ValueError:I/Ooperationonclosedfile

>>>f.close()

closed closed False

closeclosed f close

6.2.3. I/O

fileinfo.py

6.6.MP3FileInfo

try:

fsock=open(filename,"rb",0)

try:

fsock.seek(-128,2)

tagdata=fsock.read(128)

finally:

fsock.close()

.

.

.

exceptIOError:

pass

try...except open IOErrorseek IOError128read IOError try...finally open seek read

try...finally finally try“” IOError open,seek read IOError

pass Python“ ”try...except

6.2.4.

, :

"Append""write"

,,"log,"

6.7.

>>>logfile=open('test.log','w')

>>>logfile.write('testsucceeded')

>>>logfile.close()

>>>printfile('test.log').read()

testsucceeded

>>>logfile=open('test.log','a')

>>>logfile.write('line2')

>>>logfile.close()

>>>printfile('test.log').read()

testsucceededline2

test.log, "w"

open writefile open,, test.log, "a"

, test.log ,

PythonTutorial listeff-bot PythonKnowledgeBasePythonLibraryReference

<< 1234567 for>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>>for <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

6.3.for

Python for Python

Pythonlist Python for

6.8.for

>>>li=['a','b','e']

>>>forsinli:

...prints

a

b

e

>>>print"\n".join(li)

a

b

e

for list lilist s if for for joinlistfor

“ ” VisualBasic for

6.9.

>>>foriinrange(5):

...printi

0

1

2

3

4

>>>li=['a','b','c','d','e']

>>>foriinrange(len(li)):

...printli[i]

a

b

c

d

e

3.20“” rangelist, , VisualBasiclist

for fordictionary

6.10.dictionary

>>>importos

>>>fork,vinos.environ.items():

...print"%s=%s"%(k,v)

USERPROFILE=C:\DocumentsandSettings\mpilgrim

OS=Windows_NT

COMPUTERNAME=MPILGRIM

USERNAME=mpilgrim

[......]

>>>print"\n".join(["%s=%s"%(k,v)

...fork,vinos.environ.items()])

USERPROFILE=C:\DocumentsandSettings\mpilgrim

OS=Windows_NT

COMPUTERNAME=MPILGRIM

USERNAME=mpilgrim

[......]

os.environdictionaryWindowsshellexport MacOSdictionaryos.environ.items()tuplelist [(key1,value1),(key2,

value2),...] forlist key1 kvalue1 v k

=USERPROFILEv=C:\DocumentsandSettings\mpilgrim kOSv Windows_NT

list fordictionarylistlistfor print

5 fileinfo.py MP3FileInfo for

6.11.MP3FileInfo for

tagDataMap={"title":(3,33,stripnulls),

"artist":(33,63,stripnulls),

"album":(63,93,stripnulls),

"year":(93,97,stripnulls),

"comment":(97,126,stripnulls),

"genre":(127,128,ord)}

.

.

.

iftagdata[:3]=="TAG":

fortag,(start,end,parseFunc)inself.tagDataMap.items():

self[tag]=parseFunc(tagdata[start:end])

tagDataMap MP312833233-62

63-92 tagDataMaptupledictionarytuple

for itemslist items (key,value)tuplelistlist ("title",(3,33,<functionstripnulls>))

tag "title"start 3end 33parseFunc stripnulls

MP3 start end tagdata parseFunc parseFunc self tag tagDataMap self

<< 1234567 sys.modules>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>>sys.modules <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

6.4. sys.modules

Python,dictionary sys.modules

6.12.sys.modules

>>>importsys

>>>print'\n'.join(sys.modules.keys())

win32api

os.path

os

exceptions

__main__

ntpath

nt

sys

__builtin__

site

signal

UserDict

stat

sys Python sys.version sys.version_infosys.getrecursionlimit() sys.setrecursionlimit())sys.modules Python PythonPythonIDE sys.modules IDE

sys.modules

6.13. sys.modules

>>>importfileinfo

>>>print'\n'.join(sys.modules.keys())

win32api

os.path

os

fileinfo

exceptions

__main__

ntpath

nt

sys

__builtin__

site

signal

UserDict

stat

>>>fileinfo

<module'fileinfo'from'fileinfo.pyc'>

>>>sys.modules["fileinfo"]

<module'fileinfo'from'fileinfo.pyc'>

sys.modules Python sys.modules

sys.modules

sys.modulesdictionary __module__ __module__

6.14.__module__

>>>fromfileinfoimportMP3FileInfo

>>>MP3FileInfo.__module__

'fileinfo'

>>>sys.modules[MP3FileInfo.__module__]

<module'fileinfo'from'fileinfo.pyc'>

Python __module__

sys.modules

, 5 sys.modules fileinfo.py

6.15.fileinfo.py sys.modules

defgetFileInfoClass(filename,module=sys.modules[FileInfo.__module__]):

"getfileinfoclassfromfilenameextension"

subclass="%sFileInfo"%os.path.splitext(filename)[1].upper()[1:]

returnhasattr(module,subclass)andgetattr(module,subclass)

filename module module FileInfoPython sys.modules Python module module os subclass MP3FileInfo

getattr hasattr getattr,“ Ifthismodulehastheclassnamedbysubclassthenreturnit,otherwisereturnthebaseclassFileInfo subclass FileInfo”

PythonTutorialPythonLibraryReference sys

<<for 1234567 Directory>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>>Directory <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

6.5.Directoryos.path,

6.16.

>>>importos

>>>os.path.join("c:\\music\\ap\\","mahadeva.mp3")

'c:\\music\\ap\\mahadeva.mp3'

>>>os.path.join("c:\\music\\ap","mahadeva.mp3")

'c:\\music\\ap\\mahadeva.mp3'

>>>os.path.expanduser("~")

'c:\\DocumentsandSettings\\mpilgrim\\MyDocuments'

>>>os.path.join(os.path.expanduser("~"),"Python")

'c:\\DocumentsandSettings\\mpilgrim\\MyDocuments\\Python'

os.path getpass getpass os pathos.path joinWindows

join addSlashIfNecessary Python

expanduser ~Windows, UNIX MacOSX,MacOS

6.17.

>>>os.path.split("c:\\music\\ap\\mahadeva.mp3")

('c:\\music\\ap','mahadeva.mp3')

>>>(filepath,filename)=os.path.split("c:\\music\\ap\\mahadeva.mp3"

>>>filepath

'c:\\music\\ap'

>>>filename

'mahadeva.mp3'

>>>(shortname,extension)=os.path.splitext(filename)

>>>shortname

'mahadeva'

>>>extension

'.mp3'

splittuple

splittupletuplefilepath splittuplefilename splittuple

os.path splitexttuple

6.18.

>>>os.listdir("c:\\music\\_singles\\")

['a_time_long_forgotten_con.mp3','hellraiser.mp3',

'kairo.mp3','long_way_home1.mp3','sidewinder.mp3',

'spinning.mp3']

>>>dirname="c:\\"

>>>os.listdir(dirname)

['AUTOEXEC.BAT','boot.ini','CONFIG.SYS','cygwin',

'docbook','DocumentsandSettings','Incoming','Inetpub','IO.SYS',

'MSDOS.SYS','Music','NTDETECT.COM','ntldr','pagefile.sys',

'ProgramFiles','Python20','RECYCLER',

'SystemVolumeInformation','TEMP','WINNT']

>>>[fforfinos.listdir(dirname)

...ifos.path.isfile(os.path.join(dirname,f))]

['AUTOEXEC.BAT','boot.ini','CONFIG.SYS','IO.SYS','MSDOS.SYS',

'NTDETECT.COM','ntldr','pagefile.sys']

>>>[fforfinos.listdir(dirname)

...ifos.path.isdir(os.path.join(dirname,f))]

['cygwin','docbook','DocumentsandSettings','Incoming',

'Inetpub','Music','ProgramFiles','Python20','RECYCLER',

'SystemVolumeInformation','TEMP','WINNT']

listdirlistlistdir os.path isfile isfile10os.path.join isfileos.path isdir10

6.19. fileinfo.py

deflistDirectory(directory,fileExtList):

"getlistoffileinfoobjectsforfilesofparticularextensions"

fileList=[os.path.normcase(f)

forfinos.listdir(directory)]

fileList=[os.path.join(directory,f)

forfinfileList

ifos.path.splitext(f)[1]infileExtList]

os.listdir(directory) directorylist flist os.path.normcase(f)mahadeva.mp3 mahadeva.MP3Windows MacOS

normcase UNIX flist os.path.splitext(f)list fileExtList listDirectory os.path.join(directory,f)list

os os.path os.path.splitUNIX,Windows,MacOS Python

directory ,

6.20.ListingDirectorieswithglob

>>>os.listdir("c:\\music\\_singles\\")

['a_time_long_forgotten_con.mp3','hellraiser.mp3',

'kairo.mp3','long_way_home1.mp3','sidewinder.mp3',

'spinning.mp3']

>>>importglob

>>>glob.glob('c:\\music\\_singles\\*.mp3')

['c:\\music\\_singles\\a_time_long_forgotten_con.mp3',

'c:\\music\\_singles\\hellraiser.mp3',

'c:\\music\\_singles\\kairo.mp3',

'c:\\music\\_singles\\long_way_home1.mp3',

'c:\\music\\_singles\\sidewinder.mp3',

'c:\\music\\_singles\\spinning.mp3']

>>>glob.glob('c:\\music\\_singles\\s*.mp3')

['c:\\music\\_singles\\sidewinder.mp3',

'c:\\music\\_singles\\spinning.mp3']

>>>glob.glob('c:\\music\\*\\*.mp3')

, os.listdir,glob,, "*.mp3","s"".mp3",: music,, .mp3 globlist .mp3, , c:\music,

PythonKnowledgeBase osPythonLibraryReference os os.path

<<sys.modules 1234567 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

6.6.

6.21.listDirectory

deflistDirectory(directory,fileExtList):

"getlistoffileinfoobjectsforfilesofparticularextensions"

fileList=[os.path.normcase(f)

forfinos.listdir(directory)]

fileList=[os.path.join(directory,f)

forfinfileList

ifos.path.splitext(f)[1]infileExtList]

defgetFileInfoClass(filename,module=sys.modules[FileInfo.__module__]):

"getfileinfoclassfromfilenameextension"

subclass="%sFileInfo"%os.path.splitext(filename)[1].upper()[1:]

returnhasattr(module,subclass)andgetattr(module,subclass)

return[getFileInfoClass(f)(f)forfinfileList]

listDirectorydictionary c:\music\_singles\ ['.mp3']listdictionary directory fileExtList Pascal PythonlistDirectory os( os.path.splitext(filename)[1])( .upper())( [1:]) c:\music\ap\mahadeva.mp3 .mp3 MP3MP3FileInfo

FileInfo:“ ”( fileList)( f) getFileInfoClass

getFileInfoClass(f) f__init__ FileInfo __init__ self["name"]

__setitem__ __setitem__( MP3FileInfo)list

listDirectory MP3FileInfo

HTMLFileInfo HTML DOCFileInfo Word.doclistDirectory

<<Directory 1234567 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

6.7. 5 fileinfo.py

"""Frameworkforgettingfiletype-specificmetadata.

Instantiateappropriateclasswithfilename.Returnedobjectactslikea

dictionary,withkey-valuepairsforeachpieceofmetadata.

importfileinfo

info=fileinfo.MP3FileInfo("/music/ap/mahadeva.mp3")

print"\\n".join(["%s=%s"%(k,v)fork,vininfo.items()])

OruselistDirectoryfunctiontogetinfoonallfilesinadirectory.

forinfoinfileinfo.listDirectory("/music/ap/",[".mp3"]):

...

Frameworkcanbeextendedbyaddingclassesforparticularfiletypes,e.g.

HTMLFileInfo,MPGFileInfo,DOCFileInfo.Eachclassiscompletelyresponsiblefor

parsingitsfilesappropriately;seeMP3FileInfoforexample.

"""

importos

importsys

fromUserDictimportUserDict

defstripnulls(data):

"stripwhitespaceandnulls"

returndata.replace("\00","").strip()

classFileInfo(UserDict):

"storefilemetadata"

def__init__(self,filename=None):

UserDict.__init__(self)

self["name"]=filename

classMP3FileInfo(FileInfo):

"storeID3v1.0MP3tags"

tagDataMap={"title":(3,33,stripnulls),

"artist":(33,63,stripnulls),

"album":(63,93,stripnulls),

"year":(93,97,stripnulls),

"comment":(97,126,stripnulls),

"genre":(127,128,ord)}

def__parse(self,filename):

"parseID3v1.0tagsfromMP3file"

self.clear()

try:

fsock=open(filename,"rb",0)

try:

fsock.seek(-128,2)

tagdata=fsock.read(128)

finally:

fsock.close()

iftagdata[:3]=="TAG":

fortag,(start,end,parseFunc)inself.tagDataMap.items():

self[tag]=parseFunc(tagdata[start:end])

exceptIOError:

pass

def__setitem__(self,key,item):

ifkey=="name"anditem:

self.__parse(item)

FileInfo.__setitem__(self,key,item)

deflistDirectory(directory,fileExtList):

"getlistoffileinfoobjectsforfilesofparticularextensions"

fileList=[os.path.normcase(f)

forfinos.listdir(directory)]

fileList=[os.path.join(directory,f)

forfinfileList

ifos.path.splitext(f)[1]infileExtList]

defgetFileInfoClass(filename,module=sys.modules[FileInfo.__module__]):

"getfileinfoclassfromfilenameextension"

subclass="%sFileInfo"%os.path.splitext(filename)[1].upper()[1:]

returnhasattr(module,subclass)andgetattr(module,subclass)

return[getFileInfoClass(f)(f)forfinfileList]

if__name__=="__main__":

forinfoinlistDirectory("/music/_singles/",[".mp3"]):

print"\n".join(["%s=%s"%(k,v)fork,vininfo.items()])

print

:

try...except try...finally for os

<< 1234567 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

7.2.

7.1.

>>>s='100NORTHMAINROAD'

>>>s.replace('ROAD','RD.')

'100NORTHMAINRD.'

>>>s='100NORTHBROADROAD'

>>>s.replace('ROAD','RD.')

'100NORTHBRD.RD.'

>>>s[:-4]+s[-4:].replace('ROAD','RD.')

'100NORTHBROADRD.'

>>>importre

>>>re.sub('ROAD$','RD.',s)

'100NORTHBROADRD.'

'ROAD''RD.'replace 'ROAD'

s.replace'ROAD' 'BROAD' 'ROAD'replace 'ROAD'

'ROAD' 'ROAD'(s[-4:])(s[:-4]) 'STREET''ST.'s[:-6]s[-6:].replace(...)Pythonre

'ROAD$' 'ROAD' $“”^“”re.subs 'ROAD$''RD.'s 'ROAD''ROAD''ROAD's

'ROAD' 'BROAD''BROAD''ROAD'

7.2.

>>>s='100BROAD'

>>>re.sub('ROAD$','RD.',s)

'100BRD.'

>>>re.sub('\\bROAD$','RD.',s)

'100BROAD'

>>>re.sub(r'\bROAD$','RD.',s)

'100BROAD'

>>>s='100BROADROADAPT.3'

>>>re.sub(r'\bROAD$','RD.',s)

'100BROADROADAPT.3'

>>>re.sub(r'\bROAD\b','RD.',s)

'100BROADRD.APT3'

'ROAD'\b“”Python'\'“”PerlPythonPerlbug“”'r'Python'\t'r'\t''\''t'

'ROAD' 'ROAD're.sub$\b“ 'ROAD'”

<< 1234567 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

7.3.7.3.1.7.3.2.

“ MCMXLVI”“ 1946”(“ MDCCCLXXXVIII”“ 1888”)

7

I=1V=5X=10L=50C=100D=500M=1000

I1,II2, III3.VI 6(,“ 5 1”),VII 7,VIII10(I,X,C, M). 4,5 4 IIII; IV(“ 5 1”) 40XL

41 XLI,42 XLII,43 XLIII, 44 XLIV( 5010,51). 9,10: 8 VIII, 9 IX( 101), VIIII( I) 90 XC,900 CM.5 10X,VV 100C, LL.

DC 600; CD( 400,500100).CI 101; IC1001;XCIX, 10010,9 101).

“5”1055

7.3.1.

1000 M

7.3.

>>>importre

>>>pattern='^M?M?M?$'

>>>re.search(pattern,'M')

<SRE_Matchobjectat0106FB58>

>>>re.search(pattern,'MM')

<SRE_Matchobjectat0106C290>

>>>re.search(pattern,'MMM')

<SRE_Matchobjectat0106AA38>

>>>re.search(pattern,'MMMM')

>>>re.search(pattern,'')

<SRE_Matchobjectat0106F4A8>

:

^ M M

M?M03 M

$ ^ M

research( pattern)( 'M') searchsearchNone,Pythonnullvalue search 'M'

M M'MM'M M

'MMM'M'MMMM' M( $),( M) searchNone. M

7.3.2.

100=C200=CC300=CCC400=CD500=D600=DC700=DCC800=DCCC900=CM

:

CM

CD

C(0)D,C

D,3C

7.4.

>>>importre

>>>pattern='^M?M?M?(CM|CD|D?C?C?C?)$'

>>>re.search(pattern,'MCM')

<SRE_Matchobjectat01070390>

>>>re.search(pattern,'MD')

<SRE_Matchobjectat01073A50>

>>>re.search(pattern,'MMMCCC')

<SRE_Matchobjectat010748A8>

>>>re.search(pattern,'MCMC')

>>>re.search(pattern,'')

<SRE_Matchobjectat01071D98>

( ^),(M?M?M?) CM,CD, D?C?C?C?(D03 C)(),'MCM' M M CM( CD D?C?C?C?) MCM1900'MD' M, M D?C?C?C?D( C) MD1500'MMMCCC' M D?C?C?C?CCC( D) MMMCCC3300'MCMC' M M CM $( C) C D?C?C?C? CM

M D?C?C?C?

<< 1234567 {n,m}>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>>{n,m} <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

7.4. {n,m}

7.4.1.

,

7.5.

>>>importre

>>>pattern='^M?M?M?$'

>>>re.search(pattern,'M')

<_sre.SRE_Matchobjectat0x008EE090>

>>>pattern='^M?M?M?$'

>>>re.search(pattern,'MM')

<_sre.SRE_Matchobjectat0x008EEB48>

>>>pattern='^M?M?M?$'

>>>re.search(pattern,'MMM')

<_sre.SRE_Matchobjectat0x008EE090>

>>>re.search(pattern,'MMMM')

>>>

M,M(),

MM()

M,M( M) None.

7.6.From ntom

>>>pattern='^M{0,3}$'

>>>re.search(pattern,'M')

<_sre.SRE_Matchobjectat0x008EEB48>

>>>re.search(pattern,'MM')

<_sre.SRE_Matchobjectat0x008EE090>

>>>re.search(pattern,'MMM')

<_sre.SRE_Matchobjectat0x008EEDA8>

>>>re.search(pattern,'MMMM')

>>>

“ 03 M ”0313M

M

M

M M M None.

7.4.1.

7.7.

>>>pattern='^M?M?M?M?(CM|CD|D?C?C?C?)(XC|XL|L?X?X?X?)$'

>>>re.search(pattern,'MCMXL')

<_sre.SRE_Matchobjectat0x008EEB48>

>>>re.search(pattern,'MCML')

<_sre.SRE_Matchobjectat0x008EEB48>

>>>re.search(pattern,'MCMLX')

<_sre.SRE_Matchobjectat0x008EEB48>

>>>re.search(pattern,'MCMLXXX')

<_sre.SRE_Matchobjectat0x008EEB48>

>>>re.search(pattern,'MCMLXXXX')

>>>

MCM, XL, (A|B|C)“ A,B,C ” XL,XC L?X?X?

X? MCML1940.M,CM, L?X?X?X?L?X?X?X? LX MCML1950.M,CM, LX X MCMLX1960.M,CM, LX MCMLXXX 1980.M,CM, LX ie X None.MCMLXXXX

i

>>>pattern='^M?M?M?M?(CM|CD|D?C?C?C?)(XC|XL|L?X?X?X?)(IX|IV|V?I?I?I?)$'

{n,m}

7.8. {n,m}

>>>pattern='^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$'

>>>re.search(pattern,'MDLV')

<_sre.SRE_Matchobjectat0x008EEB48>

>>>re.search(pattern,'MMDCLXVI')

<_sre.SRE_Matchobjectat0x008EEB48>

>>>re.search(pattern,'MMMMDCCCLXXXVIII')

<_sre.SRE_Matchobjectat0x008EEB48>

>>>re.search(pattern,'I')

<_sre.SRE_Matchobjectat0x008EEB48>

M D?C{0,3} D0C L?X{0,3} L0XV?I{0,3}V0 I

MDLV1555.M D?C{0,3}D C L?X{0,3}LX V?I{0,3}VI

MMDCLXVI2666.M D?C{0,3}D C L?X{0,3}LX V?I{0,3}VI

MMMMDCCCLXXXVIII3888,(“ ”)4 M0 D?C{0,3}

X0 V?I{0,3} VI

M343888

<< 1234567 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

7.5.“ ”inlinedocumentation

Python

()Python #

7.9.(InlineComments)

>>>pattern="""

^#beginningofstring

M{0,4}#thousands-0to4M's

(CM|CD|D?C{0,3})#hundreds-900(CM),400(CD),0-300(0to3C's),

#or500-800(D,followedby0to3C's)

(XC|XL|L?X{0,3})#tens-90(XC),40(XL),0-30(0to3X's),

#or50-80(L,followedby0to3X's)

(IX|IV|V?I{0,3})#ones-9(IX),4(IV),0-3(0to3I's),

#or5-8(V,followedby0to3I's)

$#endofstring

"""

>>>re.search(pattern,'M',re.VERBOSE)

<_sre.SRE_Matchobjectat0x008EEB48>

>>>re.search(pattern,'MCMLXXXIX',re.VERBOSE)

<_sre.SRE_Matchobjectat0x008EEB48>

>>>re.search(pattern,'MMMMDCCCLXXXVIII',re.VERBOSE)

<_sre.SRE_Matchobjectat0x008EEB48>

>>>re.search(pattern,'M')

re.VERBOSEre

M CM,LX IXieM D?C{0,3}D C L?X{0,3}LX V?I{0,3}VI

re.VERBOSE re.search Python Python

<<{n,m} 1234567 :>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>>: <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

7.6.:

:

800-555-1212

8005551212

800.555.1212

(800)555-1212

1-800-555-1212

800-555-1212-1234

800-555-1212x1234

800-555-1212ext.1234

work1-(800)555.1212#1234

8005551212 1234.

7.10.

>>>phonePattern=re.compile(r'^(\d{3})-(\d{3})-(\d{4})$')

>>>phonePattern.search('800-555-1212').groups()

('800','555','1212')

>>>phonePattern.search('800-555-1212-1234')

>>>

(\d{3})\d{3} {3}“ ” {n,m} \d“ ”(09)“ ”

searchgroups()

7.11.

>>>phonePattern=re.compile(r'^(\d{3})-(\d{3})-(\d{4})-(\d+)$')

>>>phonePattern.search('800-555-1212-1234').groups()

('800','555','1212','1234')

>>>phonePattern.search('80055512121234')

>>>

>>>phonePattern.search('800-555-1212')

>>>

groups()

7.12.

>>>phonePattern=re.compile(r'^(\d{3})\D+(\d{3})\D+(\d{4})\D+(\d+)$'

>>>phonePattern.search('80055512121234').groups()

('800','555','1212','1234')

>>>phonePattern.search('800-555-1212-1234').groups()

('800','555','1212','1234')

>>>phonePattern.search('80055512121234')

>>>

>>>phonePattern.search('800-555-1212')

>>>

\D+ \D +“ 1” \D+

\D+-

7.13.

>>>phonePattern=re.compile(r'^(\d{3})\D*(\d{3})\D*(\d{4})\D*(\d*)$'

>>>phonePattern.search('80055512121234').groups()

('800','555','1212','1234')

>>>phonePattern.search('800.555.1212x1234').groups()

('800','555','1212','1234')

>>>phonePattern.search('800-555-1212').groups()

('800','555','1212','')

>>>phonePattern.search('(800)5551212x1234')

>>>

+ * \D+\D* +“ 1”? *“ 0”( 800)0( 555)0( 1212)0(1234) x

groups()“ 0”

7.14.

>>>phonePattern=re.compile(r'^\D*(\d{3})\D*(\d{3})\D*(\d{4})\D*(\d*)$'

>>>phonePattern.search('(800)5551212ext.1234').groups()

('800','555','1212','1234')

>>>phonePattern.search('800-555-1212').groups()

('800','555','1212','')

>>>phonePattern.search('work1-(800)555.1212#1234')

>>>

\D*0( \D*)0( 800)1( 555)1( 1212)00

1(\D*) Aargh.

7.15.

>>>phonePattern=re.compile(r'(\d{3})\D*(\d{3})\D*(\d{4})\D*(\d*)$'

>>>phonePattern.search('work1-(800)555.1212#1234').groups()

('800','555','1212','1234')

>>>phonePattern.search('800-555-1212')

('800','555','1212','')

>>>phonePattern.search('80055512121234')

('800','555','1212','1234')

^

7.16.()

>>>phonePattern=re.compile(r'''

#don'tmatchbeginningofstring,numbercanstartanywhere

(\d{3})#areacodeis3digits(e.g.'800')

\D*#optionalseparatorisanynumberofnon-digits

(\d{3})#trunkis3digits(e.g.'555')

\D*#optionalseparator

(\d{4})#restofnumberis4digits(e.g.'1212')

\D*#optionalseparator

(\d*)#extensionisoptionalandcanbeanynumberofdigits

$#endofstring

''',re.VERBOSE)

>>>phonePattern.search('work1-(800)555.1212#1234').groups()

('800','555','1212','1234')

>>>phonePattern.search('800-555-1212')

('800','555','1212','')

RegularExpressionHOWTOPythonPythonLibraryReferenceremodule.

<< 1234567 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

7.7.

^$\b\d\Dx?x10 xx*0xx+1xx{n,m}x n m

(a|b|c)abc

(x)(rememberedgroup).re.searchgroups()

“ ”

--JamieZawinski,incomp.emacs.xemacs

<<: 1234567 HTML>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>HTML>sgmllib.py <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

8.2.sgmllib.py

HTML: HTMLHTML sgmllib.py Python

HTML HTML sgmllib.py HTML

sgmllib.py: SGMLParserSGMLParser HTMLSGMLParser HTML: HTML

SGMLParser HTML8:

(Starttag) HTML <html><head><body> <pre> <br> <img>

tagnameSGMLParser start_tagname do_

<pre> start_pre do_pre SGMLParserunknown_starttag

(Endtag) HTML </html></head></body> </pre> SGMLParser

end_tagname SGMLParser(Characterreference)

&#160; SGMLParser handle_charref(Entityreference)

HTML &copy; SGMLParser HTML handle_entityref

(Comment)HTML, <!--...--> SGMLParser handle_comment

(Processinginstruction)HTML <?...> SGMLParser handle_pi

(Declaration)HTML DOCTYPE <!...> SGMLParser handle_decl

(Textdata)7 SGMLParser handle_data

Python2.0bug SGMLParser(handle_decl)DOCTYPE Python2.1

sgmllib.py sgmllib.py HTMLunknown_starttagunknown_endtaghandle_data

Windows ActivePythonIDE“ Runscript”

8.4.sgmllib.py

HTMLtoc.html( HTML,http://diveintopython.org/

c:\python23\lib>type"c:\downloads\diveintopython\html\toc\index.html"

<!DOCTYPEhtml

PUBLIC"-//W3C//DTDHTML4.01//EN""http://www.w3.org/TR/html4/strict.dtd">

<htmllang="en">

<head>

<metahttp-equiv="Content-Type"content="text/html;charset=ISO-8859-1">

<title>DiveIntoPython</title>

<linkrel="stylesheet"href="diveintopython.css"type="text/css">

......

sgmllib.py:

c:\python23\lib>pythonsgmllib.py"c:\downloads\diveintopython\html\toc\index.html"

data:'\n\n'

starttag:<htmllang="en">

data:'\n'

starttag:<head>

data:'\n'

starttag:<metahttp-equiv="Content-Type"content="text/html;charset=ISO-8859-1">

data:'\n\n'

starttag:<title>

data:'DiveIntoPython'

endtag:</title>

data:'\n'

starttag:<linkrel="stylesheet"href="diveintopython.css"type="text/css">

data:'\n'

......

:

SGMLParser HTML SGMLParser BaseHTMLProcessor8 HTML BaseHTMLProcessor Dialectizer HTMLhandle_data HTML Dialectizer Dialectizer.handle_data http://diveintopython.org/web

, locals,globalsdictionary

<<HTML 12345678910 HTML>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>HTML>HTML <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

8.3. HTML HTML SGMLParser

HTML HTML HTML file HTML

8.5.urllib

>>>importurllib

>>>sock=urllib.urlopen("http://diveintopython.org/")

>>>htmlSource=sock.read()

>>>sock.close()

>>>printhtmlSource

<!DOCTYPEhtmlPUBLIC"-//W3C//DTDHTML4.01Transitional//EN""http://www.w3.org/TR/html4/loose.dtd"><html><head>

<metahttp-equiv='Content-Type'content='text/html;charset=ISO-8859-1'>

<title>DiveIntoPython</title>

<linkrel='stylesheet'href='diveintopython.css'type='text/css'>

<linkrev='made'href='mailto:mark@diveintopython.org'>

<metaname='keywords'content='Python,DiveIntoPython,tutorial,object-oriented,programming,documentation,book,free'>

<metaname='description'content='afreePythontutorialforexperiencedprogrammers'>

</head>

<bodybgcolor='white'text='black'link='#0000FF'vlink='#840084'alink='#0000FF'>

<tablecellpadding='0'cellspacing='0'border='0'width='100%'>

<tr><tdclass='header'width='1%'valign='top'>diveintopython.org</td>

<tdwidth='99%'align='right'><hrsize='1'noshade></td></tr>

<tr><tdclass='tagline'colspan='2'>Python&nbsp;for&nbsp;experienced&nbsp;programmers</td></tr>

[......]

urllib Python URL()urllib urlopen URL urlopen

urlopen read HTML readlines

close

http://diveintopython.org/ HTML

8.6.urllister.py

,

fromsgmllibimportSGMLParser

classURLLister(SGMLParser):

defreset(self):

SGMLParser.reset(self)

self.urls=[]

defstart_a(self,attrs):

href=[vfork,vinattrsifk=='href']

ifhref:

self.urls.extend(href)

reset SGMLParser __init__ reset__init__ <a> start_a SGMLParser href nametitleattrstuplelist [(attribute,value),(attribute,

value),...] HTML <a>() attrslist list <a> href k=='href' SGMLParser attrs

8.7. urllister.py

>>>importurllib,urllister

>>>usock=urllib.urlopen("http://diveintopython.org/")

>>>parser=urllister.URLLister()

>>>parser.feed(usock.read())

>>>usock.close()

>>>parser.close()

>>>forurlinparser.urls:printurl

toc/index.html

#download

#languages

toc/index.html

appendix/history.html

download/diveintopython-html-5.0.zip

download/diveintopython-pdf-5.0.zip

download/diveintopython-word-5.0.zip

download/diveintopython-text-5.0.zip

download/diveintopython-html-flat-5.0.zip

download/diveintopython-xml-5.0.zip

download/diveintopython-common-5.0.zip

......

SGMLParser feed HTML [1]usock.read() close URL close feed HTML close

close parser.urls HTML URL()

Footnotes

[1] SGMLParser (consumer) HTML feed “

<<sgmllib.py 12345678910 BaseHTMLProcessor.py>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>HTML>BaseHTMLProcessor.py <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

8.4.BaseHTMLProcessor.py

SGMLParser SGMLParser HTML(consumer) : HTML SGMLParser SGMLParser HTML HTML(producer)

SGMLParser BaseHTMLProcessor8: unknown_starttag,unknown_endtag,handle_charref,handle_entityref,handle_comment,handle_pi,handle_declhandle_data

8.8.BaseHTMLProcessor

classBaseHTMLProcessor(SGMLParser):

defreset(self):

self.pieces=[]

SGMLParser.reset(self)

defunknown_starttag(self,tag,attrs):

strattrs="".join(['%s="%s"'%(key,value)forkey,value

self.pieces.append("<%(tag)s%(strattrs)s>"%locals())

defunknown_endtag(self,tag):

self.pieces.append("</%(tag)s>"%locals())

defhandle_charref(self,ref):

self.pieces.append("&#%(ref)s;"%locals())

defhandle_entityref(self,ref):

self.pieces.append("&%(ref)s"%locals())

ifhtmlentitydefs.entitydefs.has_key(ref):

self.pieces.append(";")

defhandle_data(self,text):

self.pieces.append(text)

defhandle_comment(self,text):

self.pieces.append("<!--%(text)s-->"%locals())

defhandle_pi(self,text):

self.pieces.append("<?%(text)s>"%locals())

defhandle_decl(self,text):

self.pieces.append("<!%(text)s>"%locals())

reset SGMLParser.__init__ self.piecesself.pieces HTML SGMLParser HTML

self.pieces self.pieceslist Pythonlist [2]

BaseHTMLProcessor( URLListerstart_a)SGMLParser unknown_starttag( tag)/list( attrs) HTML self.pieces </...> SGMLParser handle_charref HTML &#160; ref

160 ref &#...;# ref &...;( HTML HTML Python htmlentitydefs if) self.piecesHTML <!--...--> <?...>

HTML HTML( JavaScript) HTML()BaseHTMLProcessor HTML SGMLParser

SGMLParser BaseHTMLProcessor

)

8.9.BaseHTMLProcessor

defoutput(self):

"""ReturnprocessedHTMLasasinglestring"""

return"".join(self.pieces)

BaseHTMLProcessor SGMLParser HTMLself.pieces Python string join: string.join(self.pieces,"")

W3CPythonLibraryReference htmlentitydefs

Footnotes

[2]Pythonlist:listlist s=s+

newpiece s=s+newpiecelist n O(n) n O(n2)

<<HTML 12345678910 localsglobals>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>HTML>localsglobals <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

8.5.locals globals

HTML, Python Python, locals globals,dictionary

locals? :

defunknown_starttag(self,tag,attrs):

strattrs="".join(['%s="%s"'%(key,value)forkey,value

self.pieces.append("<%(tag)s%(strattrs)s>"%locals())

,, locals,,,

Pythondictionary Pythondictionary

Python

x Python:

1. - x, xPython2. - x Python3. - Python x

Python x NameError Thereisnovariablenamed'x' 3.18“” Python

Python2.2:Python( lambda) Python2.2(

lambda) Python2.1 Python2.0 Python2.2:

from__future__importnested_scopes

? ! Python ? locals

8.10.locals

>>>deffoo(arg):

...x=1

...printlocals()

...

>>>foo(7)

{'arg':7,'x':1}

>>>foo('bar')

{'arg':'bar','x':1}

foo: arg x,locals/dictionarydictionarydictionary 7foodictionary: arg(7) x(1)

Python arg( locals) locals

locals() globals() globals [3]

frommoduleimport importmodule importmodule:module.function frommoduleimport globals

8.11.globals

BaseHTMLProcessor.py:

if__name__=="__main__":

fork,vinglobals().items():

printk,"=",v

globalsdictionary itemsdictionary globals

(, Python):

c:\docbook\dip\py>pythonBaseHTMLProcessor.py

SGMLParser=sgmllib.SGMLParser

htmlentitydefs=<module'htmlentitydefs'from'C:\Python23\lib\htmlentitydefs.py'

BaseHTMLProcessor=__main__.BaseHTMLProcessor

__name__=__main__

......

SGMLParser frommoduleimport sgmllib htmlentitydefs, import htmlentitydefs,entitydefs htmlentitydefs, BaseHTMLProcessor, if__name__() __name__ __main__

__name__ __main__ globals

locals globals: getattr

locals globals

8.12.locals, globals

deffoo(arg):

x=1

printlocals()

locals()["x"]=2

print"x=",x

z=7

print"z=",z

foo(3)

globals()["z"]=8

print"z=",z

3 foo {'arg':3,'x':1}

localsdictionary,dictionary x 2 locals

x=1 x=2

locals z Python() globals:localsglobalsdictionary z=8 z=7

Footnotes

[3]

<<BaseHTMLProcessor.py12345678910 dictionary>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>HTML>dictionary <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

8.6.dictionary locals globals?dictionary,tuple

dictionarytuple

8.13.dictionary

>>>params={"server":"mpilgrim","database":"master","uid":"sa",

>>>"%(pwd)s"%params

'secret'

>>>"%(pwd)sisnotagoodpasswordfor%(uid)s"%params

'secretisnotagoodpasswordforsa'

>>>"%(database)sofmind,%(database)sofbody"%params

'masterofmind,masterofbody'

tupledictionary params %s paramsdictionary %

(pwd)s secret

dictionarydictionary KeyError

dictionarydictionary localsdictionary

8.14.BaseHTMLProcessor.pydictionary

defhandle_comment(self,text):

self.pieces.append("<!--%(text)s-->"%locals())

localsdictionary( text) text'Beginpagefooter' "<!--%(text)s-->"%locals() '<!--

Beginpagefooter-->'

8.15.dictionary

defunknown_starttag(self,tag,attrs):

strattrs="".join(['%s="%s"'%(key,value)forkey,value

self.pieces.append("<%(tag)s%(strattrs)s>"%locals())

attrs/tuplelist dictionary items :

1. attrs [('href','index.html'),('title','Gotohome

page')]

2. key 'href'value 'index.html'

3. '%s="%s"'%(key,value) 'href="index.html"'

4. key 'title'value 'Gotohomepage'

5. 'title="Gotohomepage"'

6. listlist strattrslist 'href="index.html"

title="Gotohomepage"'

dictionary tag strattrs tag 'a' '<a

href="index.html"title="Gotohomepage">' self.pieces

localsdictionary locals locals

<<localsglobals 12345678910 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>HTML> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

8.7. comp.lang.python“ HTML ”[4]( HTML HTML) HTML BaseHTMLProcessor

BaseHTMLProcessor(consume) HTML( SGMLParser) HTMLHTML

8.16.Quotingattributevalues

>>>htmlSource="""

...<html>

...<head>

...<title>Testpage</title>

...</head>

...<body>

...<ul>

...<li><ahref=index.html>Home</a></li>

...<li><ahref=toc.html>Tableofcontents</a></li>

...<li><ahref=history.html>Revisionhistory</a></li>

...</body>

...</html>

..."""

>>>fromBaseHTMLProcessorimportBaseHTMLProcessor

>>>parser=BaseHTMLProcessor()

>>>parser.feed(htmlSource)

>>>printparser.output()

<html>

<head>

<title>Testpage</title>

</head>

<body>

<ul>

<li><ahref="index.html">Home</a></li>

<li><ahref="toc.html">Tableofcontents</a></li>

<li><ahref="history.html">Revisionhistory</a></li>

</body>

</html>

<a> href( docstring IDE)

BaseHTMLProcessor output: SGMLParserHTML BaseHTMLProcessor HTML(parser.pieces) parser.output HTML

Footnotes

[4]“ Python ”(: Emacs)“ Python Perl”(:“ Perl Python ”-LarryWall19981014)

HTML

<<dictionary 12345678910 dialect.py>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>HTML>dialect.py <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

8.8.dialect.py

Dialectizer BaseHTMLProcessor() <pre>...</pre>

<pre> Dialectizer: start_pre end_pre

8.17.

defstart_pre(self,attrs):

self.verbatim+=1

self.unknown_starttag("pre",attrs)

defend_pre(self):

self.unknown_endtag("pre")

self.verbatim-=1

SGMLParser HTML <pre> start_pre():attrs() attrs/tuplelist unknown_starttag reset <pre> <pre> </pre>( 1 0() <pre>) <pre> unknown_starttag

SGMLParser </pre> end_pre

<pre>

SGMLParser() SGMLParser: <pre> </pre>

start_pre end_pre Python

8.18.SGMLParser

deffinish_starttag(self,tag,attrs):

try:

method=getattr(self,'start_'+tag)

exceptAttributeError:

try:

method=getattr(self,'do_'+tag)

exceptAttributeError:

self.unknown_starttag(tag,attrs)

return-1

else:

self.handle_starttag(tag,method,attrs)

return0

else:

self.stack.append(tag)

self.handle_starttag(tag,method,attrs)

return1

defhandle_starttag(self,tag,method,attrs):

method(attrs)

SGMLParser( unknown_starttag)SGMLParser“ ” getattr getattr self

tag 'pre' getattr( Dialectizer) start_pre

getattr AttributeError getattrtry...except AttributeError start_xxx do_xxx <br>

SGMLParser( start_xxx do_xxx start_xxx) AttributeError do_xxx getattr start_xxxdo_xxx: unknown_starttag

try...except else try...except do_xxx,;,

,,,

start_xxx do_xxx handle_starttag list( start_xxx

()

: Dialectizer <pre> </pre> handle_data

8.19. handle_data

defhandle_data(self,text):

self.pieces.append(self.verbatimandtextorself.process(text))

handle_data: BaseHTMLProcessor handle_data self.pieces<pre>...</pre> self.verbatim 0Python and-or

Dialectizer Perl dialect.py HTML ,

<< 12345678910 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>HTML> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

8.9.

8.20.translate,1

deftranslate(url,dialectName="chef"):

importurllib

sock=urllib.urlopen(url)

htmlSource=sock.read()

sock.close()

translate dialectName import Python import(800)URL

8.21.translate,2:

parserName="%sDialectizer"%dialectName.capitalize()

parserClass=globals()[parserName]

parser=parserClass()

capitalize dialectName'chef'parserName 'ChefDialectizer'

( parserName)dictionary( globals())() parserName 'ChefDialectizer'parserClassChefDialectizer

( parserClass): parserClassChefDialectizerparser ChefDialectizer

Dialectizer case( Python case if

): translate FooDialectizer 'foo'

dialectName translate translate

FooDialectizer frommoduleimport globals() translate FooDialectizer

Python URL()“ ”

Dialectizer Dialectizer dialect.pytranslate translate()(foodialect.py FooDialectizer) 'foo' translatefoodialect.py FooDialectizer

8.22.translate,3

parser.feed(htmlSource)

parser.close()

returnparser.output()

feed HTML feed feed( HTML) HTML feed close()

output BaseHTMLProcessor

“ ” URL

web

<<dialect.py 12345678910 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>HTML> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

8.10.Python sgmllib.py HTML

HTML URLlister HTML Dialectizer

:

locals() globals()dictionary

<< 12345678910 XML>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>XML> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

9.2. XML

9.5. XML()

>>>fromxml.domimportminidom

>>>xmldoc=minidom.parse('~/diveintopython/common/py/kgp/binary.xml'

frommoduleimport"."import xml domxml minidom xml.dom

.py Python lib/

9.6.

Python21/Python()

|

+--lib/()

|

+--xml/xml()

|

+--sax/xml.sax()

|

+--dom/xml.dom(minidom.py)

|

+--parsers/xml.parsers()

fromxml.domimportminidomPython“ xml dom minidom minidom ” Python Python

9.7.

>>>fromxml.domimportminidom

>>>minidom

<module'xml.dom.minidom'from'C:\Python21\lib\xml\dom\minidom.pyc'>

>>>minidom.Element

<classxml.dom.minidom.Elementat01095744>

>>>fromxml.dom.minidomimportElement

>>>Element

<classxml.dom.minidom.Elementat01095744>

>>>minidom.Element

<classxml.dom.minidom.Elementat01095744>

>>>fromxmlimportdom

>>>dom

<module'xml.dom'from'C:\Python21\lib\xml\dom\__init__.pyc'>

>>>importxml

>>>xml

<module'xml'from'C:\Python21\lib\xml\__init__.pyc'>

xml.domminidom minidom minidomElement

xml.domminidomElement Element Element

domxml xml

__init__.py __init__.pyxml.dom Node xml/dom/__init__.py xml dom

__init__.py

__init__.py __init__.py__init__.py

sax dom xml sax xmlsax.py dom

xmldom.py XML3000

Python Python

<<XML 1234567 XML>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>XML>XML <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

9.3.XML XML

9.8. XML()

>>>fromxml.domimportminidom

>>>xmldoc=minidom.parse('~/diveintopython/common/py/kgp/binary.xml'

>>>xmldoc

<xml.dom.minidom.Documentinstanceat010BE87C>

>>>printxmldoc.toxml()

<?xmlversion="1.0"?>

<grammar>

<refid="bit">

<p>0</p>

<p>1</p>

</ref>

<refid="byte">

<p><xrefid="bit"/><xrefid="bit"/><xrefid="bit"/><xrefid="bit"/>\

<xrefid="bit"/><xrefid="bit"/><xrefid="bit"/><xrefid="bit"/></p>

</ref>

</grammar>

xml.dom minidomminidom.parse XML XML

minidom.parse Document Node DocumentPython Python minidom.parse XMLtoxml Node minidom.parse Document toxmlNode XML Document XML

XML

9.9.

>>>xmldoc.childNodes

[<DOMElement:grammarat17538908>]

>>>xmldoc.childNodes[0]

<DOMElement:grammarat17538908>

>>>xmldoc.firstChild

<DOMElement:grammarat17538908>

Node childNodes Node Document XML grammar Python Python Node firstChild childNodes[0] lastChild

childNodes[-1]

9.10.toxml

>>>grammarNode=xmldoc.firstChild

>>>printgrammarNode.toxml()

<grammar>

<refid="bit">

<p>0</p>

<p>1</p>

</ref>

<refid="byte">

<p><xrefid="bit"/><xrefid="bit"/><xrefid="bit"/><xrefid="bit"/>\

<xrefid="bit"/><xrefid="bit"/><xrefid="bit"/><xrefid="bit"/></p>

</ref>

</grammar>

toxml Node XMLDocument

9.11.

>>>grammarNode.childNodes

[<DOMTextnode"\n">,<DOMElement:refat17533332>,\

<DOMTextnode"\n">,<DOMElement:refat17549660>,<DOMTextnode"\n">]

>>>printgrammarNode.firstChild.toxml()

>>>printgrammarNode.childNodes[1].toxml()

<refid="bit">

<p>0</p>

<p>1</p>

</ref>

>>>printgrammarNode.childNodes[3].toxml()

<refid="byte">

<p><xrefid="bit"/><xrefid="bit"/><xrefid="bit"/><xrefid="bit"/>\

<xrefid="bit"/><xrefid="bit"/><xrefid="bit"/><xrefid="bit"/></p>

</ref>

>>>printgrammarNode.lastChild.toxml()

binary.xml XML grammar ref'<grammar>' '<ref>' grammar '</ref>'

grammar.childNodes53 Text Element Text '<grammar>' '<ref>'

Element ref Element ref Text '</ref>' '</grammar>'

9.12.Drillingdownallthewaytotext

>>>grammarNode

<DOMElement:grammarat19167148>

>>>refNode=grammarNode.childNodes[1]

>>>refNode

<DOMElement:refat17987740>

>>>refNode.childNodes

[<DOMTextnode"\n">,<DOMTextnode"">,<DOMElement:pat19315844>,\

<DOMTextnode"\n">,<DOMTextnode"">,\

<DOMElement:pat19462036>,<DOMTextnode"\n">]

>>>pNode=refNode.childNodes[2]

>>>pNode

<DOMElement:pat19315844>

>>>printpNode.toxml()

<p>0</p>

>>>pNode.firstChild

<DOMTextnode"0">

>>>pNode.firstChild.data

u'0'

refgrammarNode.childNodes[1]childNodes[0] Text

ref p

toxmlp pNode.childNodes '0' TextText.data 'u'

<< 1234567 Unicode>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>XML>Unicode <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

9.4.UnicodeUnicode Python XMLunicode

. unicode(0-255)koi8-r241Mac241unicode

unicode2065535 [5]2Unicode

7 ASCII012765“ A”97“ a”7 ASCIIISO-8859-1“ latin-1”7Unicode7 ASCII0127ISO-8859-112825525665535

unicodeunicode

Python

2.0 Pythonunicode XMLunicode XMLunicode

9.13.unicode

>>>s=u'Divein'

>>>s

u'Divein'

>>>prints

Divein

unicode ASCII“ u” ASCIIunicode ASCII ASCIIunicode

Python ASCIIunicode ASCII ASCIIsunicode

9.14. ASCII

>>>s=u'LaPe\xf1a'

>>>prints

Traceback(innermostlast):

File"<interactiveinput>",line1,in?

UnicodeError:ASCIIencodingerror:ordinalnotinrange(128)

>>>prints.encode('latin-1')

LaPeña

unicode ASCII“ ñ”(nnunicode 0xf1(241\xf1

printunicode ASCIIunicode ASCII PythonUnicodeError

unicode sunicode print encodeunicodeunicode0127

unicode Pythonunicode ASCII

9.15.sitecustomize.py

#sitecustomize.py

#thisfilecanbeanywhereinyourPythonpath,

#butitusuallygoesin${pythondir}/lib/site-packages/

importsys

sys.setdefaultencoding('iso-8859-1')

sitecustomize.py Python importPythonlibsite-packages

setdefaultencoding Pythonunicode

9.16.

>>>importsys

>>>sys.getdefaultencoding()

'iso-8859-1'

>>>s=u'LaPe\xf1a'

>>>prints

LaPeña

sitecustomize.py Python'ascii'sitecustomize.pyPython Python Pythonsys.setdefaultencoding site.py“ setdefaultencoding”

Python

9.17. .py

Python ASCII .py .pyUTF-8

#!/usr/bin/envpython

#-*-coding:UTF-8-*-

XML XMLISO-8859-1KOI8-RXML

9.18.russiansample.xml

<?xmlversion="1.0"encoding="koi8-r"?>

<preface>

<title>Предисловие</title>

</preface>

XML koi8-r

“ Preface” koi8-r iso-8859-1

9.19. russiansample.xml

>>>fromxml.domimportminidom

>>>xmldoc=minidom.parse('russiansample.xml')

>>>title=xmldoc.getElementsByTagName('title')[0].firstChild.data

>>>title

u'\u041f\u0440\u0435\u0434\u0438\u0441\u043b\u043e\u0432\u0438\u0435'

>>>printtitle

Traceback(innermostlast):

File"<interactiveinput>",line1,in?

UnicodeError:ASCIIencodingerror:ordinalnotinrange(128)

>>>convertedtitle=title.encode('koi8-r')

>>>convertedtitle

'\xf0\xd2\xc5\xc4\xc9\xd3\xcc\xcf\xd7\xc9\xc5'

>>>printconvertedtitle

Предисловие

russiansample.xml sitecustomize.py 'ascii'

setdefaultencoding

title title Python XMLtitleunicodetitleunicode ASCII Python ASCII

koi8-runicode f0,d2,c5unicode koi8-r-koi8-r PythonIDEiso-8859-1 koi8-r

unicode XML Python XML

unicode Pythonunicode XML7 ASCIIunicode Python XML ASCIIunicode ASCII Python

Unicode.orgunicode

Unicode Pythonunicodeunicode ASCIIPEP263 .py

Footnotes

[5] unicode2unicode Python

<<XML 1234567 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>XML> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

9.5. XML XML getElementsByTagName

binary.xml

9.20.binary.xml

<?xmlversion="1.0"?>

<!DOCTYPEgrammarPUBLIC"-//diveintopython.org//DTDKantGeneratorProv1.0//EN""kgp.dtd">

<grammar>

<refid="bit">

<p>0</p>

<p>1</p>

</ref>

<refid="byte">

<p><xrefid="bit"/><xrefid="bit"/><xrefid="bit"/><xrefid="bit"/>\

<xrefid="bit"/><xrefid="bit"/><xrefid="bit"/><xrefid="bit"/></p>

</ref>

</grammar>

ref'bit''byte''0''1'8

9.21.getElementsByTagName

>>>fromxml.domimportminidom

>>>xmldoc=minidom.parse('binary.xml')

>>>reflist=xmldoc.getElementsByTagName('ref')

>>>reflist

[<DOMElement:refat136138108>,<DOMElement:refat136144292>]

>>>printreflist[0].toxml()

<refid="bit">

<p>0</p>

<p>1</p>

</ref>

>>>printreflist[1].toxml()

<refid="byte">

<p><xrefid="bit"/><xrefid="bit"/><xrefid="bit"/><xrefid="bit"/>\

<xrefid="bit"/><xrefid="bit"/><xrefid="bit"/><xrefid="bit"/></p>

</ref>

getElementsByTagName Element

9.22.

>>>firstref=reflist[0]

>>>printfirstref.toxml()

<refid="bit">

<p>0</p>

<p>1</p>

</ref>

>>>plist=firstref.getElementsByTagName("p")

>>>plist

[<DOMElement:pat136140116>,<DOMElement:pat136142172>]

>>>printplist[0].toxml()

<p>0</p>

>>>printplist[1].toxml()

<p>1</p>

reflist'bit'ref Element getElementsByTagName'bit'ref<p>

getElementsByTagName“”

9.23.

>>>plist=xmldoc.getElementsByTagName("p")

>>>plist

[<DOMElement:pat136140116>,<DOMElement:pat136142172>,<DOMElement:pat136146124>]

>>>plist[0].toxml()

'<p>0</p>'

>>>plist[1].toxml()

'<p>1</p>'

>>>plist[2].toxml()

'<p><xrefid="bit"/><xrefid="bit"/><xrefid="bit"/><xrefid="bit"/>\

<xrefid="bit"/><xrefid="bit"/><xrefid="bit"/><xrefid="bit"/></p>'

firstref p xmldoc p xmldoc XML ref

grammar p p ref'bit'ref p ref'byte'ref

<<Unicode 1234567 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>XML> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

9.6.XML XML

binary.xml

XML Python XML Python XML Python XML XMLPythonPython

XML

9.24.

>>>xmldoc=minidom.parse('binary.xml')

>>>reflist=xmldoc.getElementsByTagName('ref')

>>>bitref=reflist[0]

>>>printbitref.toxml()

<refid="bit">

<p>0</p>

<p>1</p>

</ref>

>>>bitref.attributes

<xml.dom.minidom.NamedNodeMapinstanceat0x81e0c9c>

>>>bitref.attributes.keys()

[u'id']

>>>bitref.attributes.values()

[<xml.dom.minidom.Attrinstanceat0x81d5044>]

>>>bitref.attributes["id"]

<xml.dom.minidom.Attrinstanceat0x81d5044>

Elementattributes NamedNodeMapNamedNodeMap NamedNodeMap attributes.keys() 'id'

XML unicode NamedNodeMap attributes.values() Attr NamedNodeMap NamedNodeMap __getitem__

9.25.

>>>a=bitref.attributes["id"]

>>>a

<xml.dom.minidom.Attrinstanceat0x81d5044>

>>>a.name

u'id'

>>>a.value

u'bit'

Attr XML XML bitref.attributesNamedNodeMapa.name

XMLa.value

XML XML XML Python Attr

<< 1234567 Segue>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>XML>Segue <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

9.7.SegueOKthat'sitforthehard-coreXMLstuff. getattr

minidom XML

unicode

<< 1234567 ScriptsStreams>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>ScriptsStreams > <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

10.2.UNIX

stdout stderr UNIX print stdoutPython stderr PythonIDE

stdout stderr“ ”

10.8.stdout stderr

>>>foriinrange(3):

...print'Divein'

Divein

Divein

Divein

>>>importsys

>>>foriinrange(3):

...sys.stdout.write('Divein')

DiveinDiveinDivein

>>>foriinrange(3):

...sys.stderr.write('Divein')

DiveinDiveinDivein

6.9“” Python rangestdout write print sys.stdout.write

stdout stderr PythonIDE IDE Python stdoutstderr

stdout stderr 10.1“” read write

10.9.

[you@localhostkgp]$pythonstdout.py

Divein

[you@localhostkgp]$catout.log

Thismessagewillbeloggedinsteadofdisplayed

(Windows typecat)

,

#stdout.py

importsys

print'Divein'

saveout=sys.stdout

fsock=open('out.log','w')

sys.stdout=fsock

print'Thismessagewillbeloggedinsteadofdisplayed'

sys.stdout=saveout

fsock.close()

IDE“” stdout

“ printed” IDE

stdout

stderr sys.stderr sys.stdout

10.10.

[you@localhostkgp]$pythonstderr.py

[you@localhostkgp]$caterror.log

Traceback(mostrecentlinelast):

File"stderr.py",line5,in?

raiseException,'thiserrorwillbelogged'

Exception:thiserrorwillbelogged

,

#stderr.py

importsys

fsock=open('error.log','w')

sys.stderr=fsock

raiseException,'thiserrorwillbelogged'

stderr error.log

stderr Python stderr Python stdout

10.11. stderr

>>>print'enteringfunction'

enteringfunction

>>>importsys

>>>print>>sys.stderr,'enteringfunction'

enteringfunction

print printstderrprint

MacOSWindows MS-DOS print

10.12.

[you@localhostkgp]$pythonkgp.py-gbinary.xml

01100111

[you@localhostkgp]$catbinary.xml

<?xmlversion="1.0"?>

<!DOCTYPEgrammarPUBLIC"-//diveintopython.org//DTDKantGeneratorProv1.0//EN""kgp.dtd">

<grammar>

<refid="bit">

<p>0</p>

<p>1</p>

</ref>

<refid="byte">

<p><xrefid="bit"/><xrefid="bit"/><xrefid="bit"/><xrefid="bit"/>\

<xrefid="bit"/><xrefid="bit"/><xrefid="bit"/><xrefid="bit"/></p>

</ref>

</grammar>

[you@localhostkgp]$catbinary.xml|pythonkgp.py-g-

10110001

9.1“” 0 1

binary.xmlWindows typecat)binary.xml“ |”“ ” Python( binary.xml)“ -” catbinary.xml

“ ”“ -”?

10.13. kgp.py

defopenAnything(source):

ifsource=="-":

importsys

returnsys.stdin

#trytoopenwithurllib(ifsourceishttp,ftp,orfileURL)

importurllib

try:

[...snip...]

toolbox.pyopenAnything 10.1“” 3“ -”;sys.stdinthat'sit! stdinread kgp.py

openAnything)

<<ScriptsStreams 12345678 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>ScriptsStreams > <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

10.3.kgp.py XML

ref ref p p xref xref id refref

ref xref“” ref ref“”xref xref

xref ref xref id id ref ref id

10.14.loadGrammar

defloadGrammar(self,grammar):

self.grammar=self._load(grammar)

self.refs={}

forrefinself.grammar.getElementsByTagName("ref"):

self.refs[ref.attributes["id"].value]=ref

self.refs9.5“” getElementsByTagName ref9.6“” self.refs ref idself.refs ref 9.3“XML” XML

xref id ref self.refs

10.15. ref

defdo_xref(self,node):

id=node.attributes["id"].value

self.parse(self.randomChildElement(self.refs[id]))

randomChildElement

<< 12345678 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>ScriptsStreams > <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

10.4. XML ref p p ref pp p

getElementsByTagName getElementsByTagName p p getElementsByTagName p

10.16.

defrandomChildElement(self,node):

choices=[eforeinnode.childNodes

ife.nodeType==e.ELEMENT_NODE]

chosen=random.choice(choices)

returnchosen

9.9“” childNodesHowever,9.11“” childNodesnodeType ,, xml.dom__init__.py 9.2“”

nodeType

Python random random.choice ref p

choices p chosen,

<< 12345678 Creatingseparatehandlersbynodetype>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>ScriptsStreams >Creatingseparatehandlersbynodetype <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

10.5.Creatingseparatehandlersbynodetype XML XML Python Document DocumentElement

foractual XMLtags Element Textforbitsoftext Commentforembeddedcomments Python

10.17. XML

>>>fromxml.domimportminidom

>>>xmldoc=minidom.parse('kant.xml')

>>>xmldoc

<xml.dom.minidom.Documentinstanceat0x01359DE8>

>>>xmldoc.__class__

<classxml.dom.minidom.Documentat0x01105D40>

>>>xmldoc.__class__.__name__

'Document'

kant.xml

9.2“” XMLDocument xml.domminidom.py 5.4“” __class__ Python

__name__ Python 5.3“”

XML XML Python getattr4.4“getattr”

10.18.parse, XML

defparse(self,node):

parseMethod=getattr(self,"parse_%s"%node.__class__.__name__)

parseMethod(node)

Firstoff, node Document 'parse_Document'

getattr

10.19.parse

defparse_Document(self,node):

self.parse(node.documentElement)

defparse_Text(self,node):

text=node.data

ifself.capitalizeNextWord:

self.pieces.append(text[0].upper())

self.pieces.append(text[1:])

self.capitalizeNextWord=0

else:

self.pieces.append(text)

defparse_Comment(self,node):

pass

defparse_Element(self,node):

handlerMethod=getattr(self,"do_%s"%node.tagName)

handlerMethod(node)

parse_Document XMLDocument XMLDocumentturnaroundparse_Textparse_Commentpass parse parse_Comment

parse

parse_Element 'do_xref' <xref>

<p> <choice>

parseparse_Element 16 FunctionalProgramming

<< 12345678 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>ScriptsStreams > <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

10.6.Python XML

Python

10.20.sys.argv

,

#argecho.py

importsys

forarginsys.argv:

printarg

sys.argv

10.21.sys.argv

[you@localhostpy]$pythonargecho.py

argecho.py

[you@localhostpy]$pythonargecho.pyabcdef

argecho.py

abc

def

[you@localhostpy]$pythonargecho.py--help

argecho.py

--help

[you@localhostpy]$pythonargecho.py-mkant.xml

argecho.py

-m

kant.xml

sys.argv 16 FunctionalProgrammingsys.argv

--helpsys.argv

-mkant.xml sys.argv

butthenagain,itdoesn'tlooklikeit'sgoingtobeallthateasytoactuallyuseit. sys.argv[1]

10.22.getopt

defmain(argv):

grammar="kant.xml"

try:

opts,args=getopt.getopt(argv,"hg:d",["help","grammar="

exceptgetopt.GetoptError:

usage()

sys.exit(2)

...

if__name__=="__main__":

main(sys.argv[1:])

Firstoff main sys.argv[1:] sys.argv[0]

getoptgetopt sys.argv[1:]

getopt getopt UNIX usage

getopt main

"hg:d"

-h

printusagesummary-g...

usespecifiedgrammarfileorURL-d

showdebugginginformationwhileparsing

-gweb getoptg getopt

Tofurthercomplicatethings -h --help getopt

["help","grammar="]

--help

printusagesummary--grammar...

usespecifiedgrammarfileorURL

1. getopt2. --grammar -g "grammar="

3. -d -d

10.23. kgp.py

defmain(argv):

grammar="kant.xml"

try:

opts,args=getopt.getopt(argv,"hg:d",["help","grammar="

exceptgetopt.GetoptError:

usage()

sys.exit(2)

foropt,arginopts:

ifoptin("-h","--help"):

usage()

sys.exit()

elifopt=='-d':

global_debug

_debug=1

elifoptin("-g","--grammar"):

grammar=arg

source="".join(args)

k=KantGenerator(grammar,source)

printk.output()

grammar -g--grammar

getoptoptsflag argument arg Nonegetopt -h opt"-h"--help opt"--help"

-dWhat,youthoughtalltheseexamplesworkedonthefirsttry?

-g--grammar arggrammar main

That’sit getoptargs args source

<<Creatingseparatehandlersbynodetype 12345678 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>ScriptsStreams > <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

10.7.

getopt

defmain(argv):

...

try:

opts,args=getopt.getopt(argv,"hg:d",["help","grammar="

exceptgetopt.GetoptError:

...

foropt,arginopts:

...

KantGenerator

k=KantGenerator(grammar,source)

KantGenerator XML openAnything minidom XMLPython

def_load(self,source):

sock=toolbox.openAnything(source)

xmldoc=minidom.parse(sock).documentElement

sock.close()

XML XML

defloadGrammar(self,grammar):

forrefinself.grammar.getElementsByTagName("ref"):

self.refs[ref.attributes["id"].value]=ref

“”

defgetDefaultSource(self):

xrefs={}

forxrefinself.grammar.getElementsByTagName("xref"):

xrefs[xref.attributes["id"].value]=1

xrefs=xrefs.keys()

standaloneXrefs=[eforeinself.refs.keys()ifenotinxrefs]

return'<xrefid="%s"/>'%random.choice(standaloneXrefs)

XML

defparse_Element(self,node):

handlerMethod=getattr(self,"do_%s"%node.tagName)

handlerMethod(node)

p

defdo_p(self,node):

...

ifdoit:

forchildinnode.childNodes:self.parse(child)

choice

defdo_choice(self,node):

self.parse(self.randomChildElement(node))

ref xref

defdo_xref(self,node):

id=node.attributes["id"].value

self.parse(self.randomChildElement(self.refs[id]))

defparse_Text(self,node):

text=node.data

...

self.pieces.append(text)

defmain(argv):

...

k=KantGenerator(grammar,source)

printk.output()

<< 12345678 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>ScriptsStreams > <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

10.8.Python XML minidom XML PythonPython“”

getattr getopt

<< 12345678 HTTPWeb>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>HTTPWeb>HTTP <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

11.2.HTTPHTTP,Atomfeed;,,

11.2.feed

>>>importurllib

>>>data=urllib.urlopen('http://diveintomark.org/xml/atom.xml').read()

>>>printdata

<?xmlversion="1.0"encoding="iso-8859-1"?>

<feedversion="0.3"

xmlns="http://purl.org/atom/ns#"

xmlns:dc="http://purl.org/dc/elements/1.1/"

xml:lang="en">

<titlemode="escaped">diveintomark</title>

<linkrel="alternate"type="text/html"href="http://diveintomark.org/"/>

<--restoffeedomittedforbrevity-->

PythonHTTP;, urllib urlopen, read()

? ,feed,feedwebweb,feed,

HTTP

<<HTTPWeb 12345678910 HTTP>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>HTTPWeb>HTTP <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

11.3.HTTP11.3.1.(User-Agent)11.3.2.(Redirects)11.3.3.Last-Modified/If-Modified-Since11.3.4.ETag/If-None-Match11.3.5.(Compression)

HTTP

11.3.1.( User-Agent)

User-AgentHTTPweb,feedweb

Python User-Agent:Python-urllib/1.15 , User-Agent

11.3.2.(Redirects)

Web,web http://example.com/xml/atom.xml ,http://www.example.com/index.xml http://server-farm-

1.example.com/index.xml

HTTP, errors)

HTTP 302 ;“ , ”( Location:) 301 ;“ , ”( Location:) 302,HTTP,,,

HTTP, urllib.urlopen“ ”,,“ ”,

:! ,

11.3.3.Last-Modified/If-Modified-Since

CNN.com,Google.com(logo,)HTTP

(,),: If-Modified-Since,304,“ ” ? 304,

,,--

PythonURL,,

11.3.4.ETag/If-None-Match

ETag: hash(None-Match:ETaghash,, 304 , ,ETaghash,hash,

PythonURLETag,

11.3.5.(Compression)

HTTPgzipHTTPweb,XMLXML,,HTTP,,, Content-encoding:gzip

PythonURLgzip, Python

feed HTTP

<<HTTP 12345678910 HTTPweb>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>HTTPWeb>HTTPweb <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

11.4.HTTPweb, PythonHTTP ,

11.3.HTTP

>>>importhttplib

>>>httplib.HTTPConnection.debuglevel=1

>>>importurllib

>>>feeddata=urllib.urlopen('http://diveintomark.org/xml/atom.xml'

connect:(diveintomark.org,80)

send:'

GET/xml/atom.xmlHTTP/1.0

Host:diveintomark.org

User-agent:Python-urllib/1.15

'

reply:'HTTP/1.1200OK\r\n'

header:Date:Wed,14Apr200422:27:30GMT

header:Server:Apache/2.0.49(DebianGNU/Linux)

header:Content-Type:application/atom+xml

header:Last-Modified:Wed,14Apr200422:14:38GMT

header:ETag:"e8284-68e0-4de30f80"

header:Accept-Ranges:bytes

header:Content-Length:26848

header:Connection:close

urllib Python, httplib importhttplib(urllib),urllib HTTPConnectionHTTP ,HTTP Atomfeed, urllib HTTPverb,(), POST, Host, ,HTTP

User-Agent urllib User-Agent,( feeddata) 200,“ , ” ,,Atomfeed,,Atomfeed( application/atom+xml,Atomfeeds)Atomfeed,(,13) feed,Atomfeed "e8284-68e0-4de30f80"ETaghash hash;feed,

<<HTTP 12345678910 User-Agent>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>HTTPWeb>User-Agent <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

11.5. User-Agent

HTTPweb User-Agent, urllib urllib2

11.4.urllib2

>>>importhttplib

>>>httplib.HTTPConnection.debuglevel=1

>>>importurllib2

>>>request=urllib2.Request('http://diveintomark.org/xml/atom.xml'

>>>opener=urllib2.build_opener()

>>>feeddata=opener.open(request).read()

connect:(diveintomark.org,80)

send:'

GET/xml/atom.xmlHTTP/1.0

Host:diveintomark.org

User-agent:Python-urllib/2.1

'

reply:'HTTP/1.1200OK\r\n'

header:Date:Wed,14Apr200423:23:12GMT

header:Server:Apache/2.0.49(DebianGNU/Linux)

header:Content-Type:application/atom+xml

header:Last-Modified:Wed,14Apr200422:14:38GMT

header:ETag:"e8284-68e0-4de30f80"

header:Accept-Ranges:bytes

header:Content-Length:26848

header:Connection:close

PythonIDE,, HTTP urllib2HTTP, Request,URL

URL(opener) , RequestURL ,

11.5. Request

>>>request

<urllib2.Requestinstanceat0x00250AA8>

>>>request.get_full_url()

http://diveintomark.org/xml/atom.xml

>>>request.add_header('User-Agent',

...'OpenAnything/1.0+http://diveintopython.org/')

>>>feeddata=opener.open(request).read()

connect:(diveintomark.org,80)

send:'

GET/xml/atom.xmlHTTP/1.0

Host:diveintomark.org

User-agent:OpenAnything/1.0+http://diveintopython.org/

'

reply:'HTTP/1.1200OK\r\n'

header:Date:Wed,14Apr200423:45:17GMT

header:Server:Apache/2.0.49(DebianGNU/Linux)

header:Content-Type:application/atom+xml

header:Last-Modified:Wed,14Apr200422:14:38GMT

header:ETag:"e8284-68e0-4de30f80"

header:Accept-Ranges:bytes

header:Content-Length:26848

header:Connection:close

;URL RequestRequest add_header,HTTP ,:,, ,,URL

opener,feed, User-Agent User-Agent, Python User-Agent User-Agent

User-agent ? urllib2HTTP

<<HTTPweb 12345678910 Last-ModifiedETag>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>HTTPWeb>Last-ModifiedETag <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

11.6. Last-Modified ETag

webHTTP, Last-Modified ETag

, httplib.HTTPConnection.debuglevel=0,

11.6. Last-Modified

>>>importurllib2

>>>request=urllib2.Request('http://diveintomark.org/xml/atom.xml'

>>>opener=urllib2.build_opener()

>>>firstdatastream=opener.open(request)

>>>firstdatastream.headers.dict

{'date':'Thu,15Apr200420:42:41GMT',

'server':'Apache/2.0.49(DebianGNU/Linux)',

'content-type':'application/atom+xml',

'last-modified':'Thu,15Apr200419:45:21GMT',

'etag':'"e842a-3e53-55d97640"',

'content-length':'15955',

'accept-ranges':'bytes',

'connection':'close'}

>>>request.add_header('If-Modified-Since',

...firstdatastream.headers.get('Last-Modified'))

>>>seconddatastream=opener.open(request)

Traceback(mostrecentcalllast):

File"<stdin>",line1,in?

File"c:\python23\lib\urllib2.py",line326,inopen

'_open',req)

File"c:\python23\lib\urllib2.py",line306,in_call_chain

result=func(*args)

File"c:\python23\lib\urllib2.py",line901,inhttp_open

returnself.do_open(httplib.HTTP,req)

File"c:\python23\lib\urllib2.py",line895,indo_open

returnself.parent.error('http',req,fp,code,msg,hdrs)

File"c:\python23\lib\urllib2.py",line352,inerror

returnself._call_chain(*args)

File"c:\python23\lib\urllib2.py",line306,in_call_chain

result=func(*args)

File"c:\python23\lib\urllib2.py",line412,inhttp_error_default

raiseHTTPError(req.get_full_url(),code,msg,hdrs,fp)

urllib2.HTTPError:HTTPError304:NotModified

HTTP? HTTP, If-Modified-Since , 304, urllib2, HTTPError, 304

,,;

urllib2 HTTPError, 404(pagenotfound) , 200(OK),301(permanentredirect), 302(temporaryredirect) HTTPError ,,,URL

11.7.URL

URL openanything.py

classDefaultErrorHandler(urllib2.HTTPDefaultErrorHandler):

defhttp_error_default(self,req,fp,code,msg,headers):

result=urllib2.HTTPError(

req.get_full_url(),code,msg,headers,fp)

result.status=code

returnresult

urllib2URL 9 XML 304, urllib2 http_error_default, urllib2

, HTTPError,:,HTTP

11.8.URL

>>>request.headers

{'If-modified-since':'Thu,15Apr200419:45:21GMT'}

>>>importopenanything

>>>opener=urllib2.build_opener(

...openanything.DefaultErrorHandler())

>>>seconddatastream=opener.open(request)

>>>seconddatastream.status

304

>>>seconddatastream.read()

''

, Request, If-Modified-Since[todo]:URL, urllib2 urllib2HTTPHTTPURL,,( seconddatastream.headers.dict),HTTP ,, 304, 304, :,

ETag, Last-Modified If-Modified-Since, ETag If-

None-Match IDE

11.9.SupportingETag/If-None-Match

>>>importurllib2,openanything

>>>request=urllib2.Request('http://diveintomark.org/xml/atom.xml'

>>>opener=urllib2.build_opener(

...openanything.DefaultErrorHandler())

>>>firstdatastream=opener.open(request)

>>>firstdatastream.headers.get('ETag')

'"e842a-3e53-55d97640"'

>>>firstdata=firstdatastream.read()

>>>printfirstdata

<?xmlversion="1.0"encoding="iso-8859-1"?>

<feedversion="0.3"

xmlns="http://purl.org/atom/ns#"

xmlns:dc="http://purl.org/dc/elements/1.1/"

xml:lang="en">

<titlemode="escaped">diveintomark</title>

<linkrel="alternate"type="text/html"href="http://diveintomark.org/"/>

<--restoffeedomittedforbrevity-->

>>>request.add_header('If-None-Match',

...firstdatastream.headers.get('ETag'))

>>>seconddatastream=opener.open(request)

>>>seconddatastream.status

304

>>>seconddatastream.read()

''

firstdatastream.headers, ETag( ETag?None.)OK, If-None-Match ETag

(), 304 ETag, 304 Last-Modified ETaghash, 304

,HTTP Last-Modified ETag,web,

,

<<User-Agent 12345678910 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>HTTPWeb> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

11.7.URL

,

11.10.web

>>>importurllib2,httplib

>>>httplib.HTTPConnection.debuglevel=1

>>>request=urllib2.Request(

...'http://diveintomark.org/redir/example301.xml')

>>>opener=urllib2.build_opener()

>>>f=opener.open(request)

connect:(diveintomark.org,80)

send:'

GET/redir/example301.xmlHTTP/1.0

Host:diveintomark.org

User-agent:Python-urllib/2.1

'

reply:'HTTP/1.1301MovedPermanently\r\n'

header:Date:Thu,15Apr200422:06:25GMT

header:Server:Apache/2.0.49(DebianGNU/Linux)

header:Location:http://diveintomark.org/xml/atom.xml

header:Content-Length:338

header:Connection:close

header:Content-Type:text/html;charset=iso-8859-1

connect:(diveintomark.org,80)

send:'

GET/xml/atom.xmlHTTP/1.0

Host:diveintomark.org

User-agent:Python-urllib/2.1

'

reply:'HTTP/1.1200OK\r\n'

header:Date:Thu,15Apr200422:06:25GMT

header:Server:Apache/2.0.49(DebianGNU/Linux)

header:Last-Modified:Thu,15Apr200419:45:21GMT

header:ETag:"e842a-3e53-55d97640"

header:Accept-Ranges:bytes

header:Content-Length:15955

header:Connection:close

header:Content-Type:application/atom+xml

>>>f.url

'http://diveintomark.org/xml/atom.xml'

>>>f.headers.dict

{'content-length':'15955',

'accept-ranges':'bytes',

'server':'Apache/2.0.49(DebianGNU/Linux)',

'last-modified':'Thu,15Apr200419:45:21GMT',

'connection':'close',

'etag':'"e842a-3e53-55d97640"',

'date':'Thu,15Apr200422:06:25GMT',

'content-type':'application/atom+xml'}

>>>f.status

Traceback(mostrecentcalllast):

File"<stdin>",line1,in?

AttributeError:addinfourlinstancehasnoattribute'status'

Atomfeedhttp://diveintomark.org/xml/atom.xml,, 301, Location:

urllib2Location: opener()

, urllib2 301 302,

11.11.

openanything.py

classSmartRedirectHandler(urllib2.HTTPRedirectHandler):

defhttp_error_301(self,req,fp,code,msg,headers):

result=urllib2.HTTPRedirectHandler.http_error_301(

self,req,fp,code,msg,headers)

result.status=code

returnresult

defhttp_error_302(self,req,fp,code,msg,headers):

result=urllib2.HTTPRedirectHandler.http_error_302(

self,req,fp,code,msg,headers)

result.status=code

returnresult

urllib2 HTTPRedirectHandler ,,HTTPRedirectHandler, 301, urllib2 http_error_301 http_error_301

, Location::,( 301),( 302): http_error_302,,

? URL,,

11.12.

>>>request=urllib2.Request('http://diveintomark.org/redir/example301.xml'

>>>importopenanything,httplib

>>>httplib.HTTPConnection.debuglevel=1

>>>opener=urllib2.build_opener(

...openanything.SmartRedirectHandler())

>>>f=opener.open(request)

connect:(diveintomark.org,80)

send:'GET/redir/example301.xmlHTTP/1.0

Host:diveintomark.org

User-agent:Python-urllib/2.1

'

reply:'HTTP/1.1301MovedPermanently\r\n'

header:Date:Thu,15Apr200422:13:21GMT

header:Server:Apache/2.0.49(DebianGNU/Linux)

header:Location:http://diveintomark.org/xml/atom.xml

header:Content-Length:338

header:Connection:close

header:Content-Type:text/html;charset=iso-8859-1

connect:(diveintomark.org,80)

send:'

GET/xml/atom.xmlHTTP/1.0

Host:diveintomark.org

User-agent:Python-urllib/2.1

'

reply:'HTTP/1.1200OK\r\n'

header:Date:Thu,15Apr200422:13:21GMT

header:Server:Apache/2.0.49(DebianGNU/Linux)

header:Last-Modified:Thu,15Apr200419:45:21GMT

header:ETag:"e842a-3e53-55d97640"

header:Accept-Ranges:bytes

header:Content-Length:15955

header:Connection:close

header:Content-Type:application/atom+xml

>>>f.status

301

>>>f.url

'http://diveintomark.org/xml/atom.xml'

,URL, 301, http_error_301,(http://diveintomark.org/xml/atom.xml):,URL,,(http://diveintomark.org/xml/atom.xml ,

11.13.

>>>request=urllib2.Request(

...'http://diveintomark.org/redir/example302.xml')

>>>f=opener.open(request)

connect:(diveintomark.org,80)

send:'

GET/redir/example302.xmlHTTP/1.0

Host:diveintomark.org

User-agent:Python-urllib/2.1

'

reply:'HTTP/1.1302Found\r\n'

header:Date:Thu,15Apr200422:18:21GMT

header:Server:Apache/2.0.49(DebianGNU/Linux)

header:Location:http://diveintomark.org/xml/atom.xml

header:Content-Length:314

header:Connection:close

header:Content-Type:text/html;charset=iso-8859-1

connect:(diveintomark.org,80)

send:'

GET/xml/atom.xmlHTTP/1.0

Host:diveintomark.org

User-agent:Python-urllib/2.1

'

reply:'HTTP/1.1200OK\r\n'

header:Date:Thu,15Apr200422:18:21GMT

header:Server:Apache/2.0.49(DebianGNU/Linux)

header:Last-Modified:Thu,15Apr200419:45:21GMT

header:ETag:"e842a-3e53-55d97640"

header:Accept-Ranges:bytes

header:Content-Length:15955

header:Connection:close

header:Content-Type:application/atom+xml

>>>f.status

302

>>>f.url

http://diveintomark.org/xml/atom.xml

URL http://diveintomark.org/xml/atom.xml 302, Location:urllib2 http_error_302, urllib2.HTTPRedirectHandler

, http_error_302( 302), http://diveintomark.org/xml/atom.xml f.status,(http://diveintomark.org/redir/example302.xml) , ,

<<Last-ModifiedETag 12345678910 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>HTTPWeb> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

11.8.HTTP web,60%

11.14.

>>>importurllib2,httplib

>>>httplib.HTTPConnection.debuglevel=1

>>>request=urllib2.Request('http://diveintomark.org/xml/atom.xml'

>>>request.add_header('Accept-encoding','gzip')

>>>opener=urllib2.build_opener()

>>>f=opener.open(request)

connect:(diveintomark.org,80)

send:'

GET/xml/atom.xmlHTTP/1.0

Host:diveintomark.org

User-agent:Python-urllib/2.1

Accept-encoding:gzip

'

reply:'HTTP/1.1200OK\r\n'

header:Date:Thu,15Apr200422:24:39GMT

header:Server:Apache/2.0.49(DebianGNU/Linux)

header:Last-Modified:Thu,15Apr200419:45:21GMT

header:ETag:"e842a-3e53-55d97640"

header:Accept-Ranges:bytes

header:Vary:Accept-Encoding

header:Content-Encoding:gzip

header:Content-Length:6289

header:Connection:close

header:Content-Type:application/atom+xml

: Request, Accept-encodinggzip, gzipweb99%

: Content-Encoding:gzipgzipContent-Length, ,15955,gzip60%!

11.15.

>>>compresseddata=f.read()

>>>len(compresseddata)

6289

>>>importStringIO

>>>compressedstream=StringIO.StringIO(compresseddata)

>>>importgzip

>>>gzipper=gzip.GzipFile(fileobj=compressedstream)

>>>data=gzipper.read()

>>>printdata

<?xmlversion="1.0"encoding="iso-8859-1"?>

<feedversion="0.3"

xmlns="http://purl.org/atom/ns#"

xmlns:dc="http://purl.org/dc/elements/1.1/"

xml:lang="en">

<titlemode="escaped">diveintomark</title>

<linkrel="alternate"type="text/html"href="http://diveintomark.org/"/>

<--restoffeedomittedforbrevity-->

>>>len(data)

15955

, fURL read(),gzip,OK, Python gzip,()gzip

, ( compresseddata

StringIO , GzipFile,“ file” compressedstream

: GzipFile“ ” ? , gzipper

“file”; gzipper StringIO“ ”, compresseddata

? HTTP, urllib2.build_opener

,(15955bytes)

“! ” “! ” opener.open, StringIO

? OK,,,

11.16.

>>>f=opener.open(request)

>>>f.headers.get('Content-Encoding')

'gzip'

>>>data=gzip.GzipFile(fileobj=f).read()

Traceback(mostrecentcalllast):

File"<stdin>",line1,in?

File"c:\python23\lib\gzip.py",line217,inread

self._read(readsize)

File"c:\python23\lib\gzip.py",line252,in_read

pos=self.fileobj.tell()#Savecurrentposition

AttributeError:addinfourlinstancehasnoattribute'tell'

, Accept-encoding:gzip Request() Content-Encoding

opener.open,,gzip, GzipFile? GzipFile

“ ”,HTTP“ ” ,“file”;, StringIO:, StringIO,

<< 12345678910 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>HTTPWeb> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

11.9.HTTPweb

11.17.openanything

openanything.py

defopenAnything(source,etag=None,lastmodified=None,agent=USER_AGENT):

#non-HTTPcodeomittedforbrevity

ifurlparse.urlparse(source)[0]=='http':

#openURLwithurllib2

request=urllib2.Request(source)

request.add_header('User-Agent',agent)

ifetag:

request.add_header('If-None-Match',etag)

iflastmodified:

request.add_header('If-Modified-Since',lastmodified)

request.add_header('Accept-encoding','gzip')

opener=urllib2.build_opener(SmartRedirectHandler(),DefaultErrorHandler())

returnopener.open(request)

urlparseURL urlparse,URL(scheme,domain,path,params,)tuple ,scheme,HTTPURL(urllib2) User-AgentHTTP User-Agent,,openanything.py urllib2 ETag, If-None-Match, If-Modified-Since

URLURL: SmartRedirectHandler 301 302,

DefaultErrorHandler 304,404

! URL

11.18.fetch

openanything.py

deffetch(source,etag=None,last_modified=None,agent=USER_AGENT):

'''FetchdataandmetadatafromaURL,file,stream,orstring'''

result={}

f=openAnything(source,etag,last_modified,agent)

result['data']=f.read()

ifhasattr(f,'headers'):

#saveETag,iftheserversentone

result['etag']=f.headers.get('ETag')

#saveLast-Modifiedheader,iftheserversentone

result['lastmodified']=f.headers.get('Last-Modified')

iff.headers.get('content-encoding','')=='gzip':

#datacamebackgzip-compressed,decompressit

result['data']=gzip.GzipFile(fileobj=StringIO(result[

ifhasattr(f,'url'):

result['url']=f.url

result['status']=200

ifhasattr(f,'status'):

result['status']=f.status

f.close()

returnresult

,URL, ETaghash,Last-Modified User-AgentopenAnything ;,

ETaghash,, openAnything, If-None-Match Last-Modified,URL, 200

URL,

11.19. openanything.py

>>>importopenanything

>>>useragent='MyHTTPWebServicesApp/1.0'

>>>url='http://diveintopython.org/redir/example301.xml'

>>>params=openanything.fetch(url,agent=useragent)

>>>params

{'url':'http://diveintomark.org/xml/atom.xml',

'lastmodified':'Thu,15Apr200419:45:21GMT',

'etag':'"e842a-3e53-55d97640"',

'status':301,

'data':'<?xmlversion="1.0"encoding="iso-8859-1"?>

<feedversion="0.3"

<--restofdataomittedforbrevity-->'}

>>>ifparams['status']==301:

...url=params['url']

>>>newparams=openanything.fetch(

...url,params['etag'],params['lastmodified'],useragent)

>>>newparams

{'url':'http://diveintomark.org/xml/atom.xml',

'lastmodified':None,

'etag':'"e842a-3e53-55d97640"',

'status':304,

'data':''}

, ETaghash Last-Modified, (They're)

dictionary,,HTTP openanythinggzip; 301,,URL,:URL(), ETag, Last-Modified,User-Agent

dictionary,, 304

<< 12345678910 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>HTTPWeb> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

11.10.openanything.py

5HTTPweb:

User-Agent Last-Modified ETaghash gzip

<< 12345678910 SOAPWeb>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>SOAPWeb>SOAP <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

12.2.SOAP12.2.1.PyXML12.2.2.fpconst12.2.3.SOAPpy

, Python

SOAPweb,: PyXML,fpconst SOAPpy

12.2.1. PyXML

PyXML XML 9 XML

12.1.

PyXML

1. http://pyxml.sourceforge.net/Downloads

2. Windows PyXML Python

3. Windows PyXML0.8.3 Python2.3 PyXML-

0.8.3.win32-py2.3.exe.

4.

5.

PyXML PythonIDE XML

12.3. PyXML

>>>importxml

>>>xml.__version__

'0.8.3'

PyXML

12.2.2. fpconst

fpconstIEEE754double-precisionNot-a-Number(NaN),PositiveInfinity(Inf)NegativeInfinity(-Inf) SOAP

12.2.

fpconst

1. http://www.analytics.washington.edu/statcomp/projects/rzope/fpconst/ fpconst

2. .tar.gz .zipWindows .zip .tar.gz

3. WindowsXP“”WindowsWinZip MacOSX

4.

5. pythonsetup.pyinstall

fpconst PythonIDE

12.4. fpconst

>>>importfpconst

>>>fpconst.__version__

'0.6.0'

fpconst

12.2.3. SOAPpy

SOAP SOAPpy

12.3.

SOAPpy

1. http://pywebsvcs.sourceforge.net/ SOAPpy

2. Windows .zip .tar.gz

3. fpconst

4. SOAPpy

5. pythonsetup.pyinstall

SOAPpy PythonIDE

12.5. SOAPpy

>>>importSOAPpy

>>>SOAPpy.__version__

'0.11.4'

SOAPpy

<<SOAPWeb 123456789 SOAP>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>SOAPWeb>SOAP <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

12.3. SOAP SOAP SOAP

SOAP http://www.xmethods.net/

12.6.

>>>fromSOAPpyimportSOAPProxy

>>>url='http://services.xmethods.net:80/soap/servlet/rpcrouter'

>>>namespace='urn:xmethods-Temperature'

>>>server=SOAPProxy(url,namespace)

>>>server.getTemp('27502')

80.0

SOAPProxyproxy SOAPproxy SOAPXMLHTTP SOAPXML Python

SOAP URL URLGoogle APIURL SOAPnamespace SOAP URL Python packages URL SOAPProxy SOAP Python SOAP

<<SOAP 123456789 SOAP>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>SOAPWeb>SOAP <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

12.4.SOAPSOAP

SOAPProxy

12.7.SOAP

>>>fromSOAPpyimportSOAPProxy

>>>url='http://services.xmethods.net:80/soap/servlet/rpcrouter'

>>>n='urn:xmethods-Temperature'

>>>server=SOAPProxy(url,namespace=n)

>>>server.config.dumpSOAPOut=1

>>>server.config.dumpSOAPIn=1

>>>temperature=server.getTemp('27502')

***OutgoingSOAP******************************************************

<?xmlversion="1.0"encoding="UTF-8"?>

<SOAP-ENV:EnvelopeSOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"

xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"

xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"

xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"

xmlns:xsd="http://www.w3.org/1999/XMLSchema">

<SOAP-ENV:Body>

<ns1:getTempxmlns:ns1="urn:xmethods-Temperature"SOAP-ENC:root="1">

<v1xsi:type="xsd:string">27502</v1>

</ns1:getTemp>

</SOAP-ENV:Body>

</SOAP-ENV:Envelope>

************************************************************************

***IncomingSOAP******************************************************

<?xmlversion='1.0'encoding='UTF-8'?>

<SOAP-ENV:Envelopexmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<SOAP-ENV:Body>

<ns1:getTempResponsexmlns:ns1="urn:xmethods-Temperature"

SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">

<returnxsi:type="xsd:float">80.0</return>

</ns1:getTempResponse>

</SOAP-ENV:Body>

</SOAP-ENV:Envelope>

************************************************************************

>>>temperature

80.0

URL SOAPProxy

server.config.dumpSOAPIn server.config.dumpSOAPOut

SOAP SOAPXMLXML SOAPProxy

XML SOAP“ ”<Body>

<ns1:getTemp

xmlns:ns1="urn:xmethods-Temperature"

SOAP-ENC:root="1">

<v1xsi:type="xsd:string">27502</v1>

</ns1:getTemp>

getTemp SOAPProxy getattrXMLXML SOAPProxy SOAP-ENC:rootXML SOAPProxystring xsi:type

XML <Body>

<ns1:getTempResponse

xmlns:ns1="urn:xmethods-Temperature"

SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"

<returnxsi:type="xsd:float">80.0</return>

</ns1:getTempResponse>

<getTempResponse> Response SOAPProxy

SOAPProxy SOAPProxyfloat SOAPProxy Python

<<SOAP 123456789 WSDL>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>SOAPWeb>WSDL <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

12.5.WSDLSOAPProxy SOAP SOAPProxy

SOAP URL

URL Python

4 Python

WSDL SOAP WSDL“ WebServicesDescriptionLanguage ” SOAP

WSDLXML SOAPGoogleAPIWSDLGoogle WSDLGoogle

WSDL SOAP

URL SOAP WSDL

WSDL SOAP

<<SOAP 123456789 WSDLSOAP>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>SOAPWeb>WSDLSOAP <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

12.6. WSDL SOAP WSDL WSDL

WSDL SOAP

12.8.

>>>fromSOAPpyimportWSDL

>>>wsdlFile='http://www.xmethods.net/sd/2001/TemperatureService.wsdl'

>>>server=WSDL.Proxy(wsdlFile)

>>>server.methods.keys()

[u'getTemp']

SOAPpy WSDL WSDL WSDLproxy WSDL.Proxy WSDL WSDL URLproxy WSDL WSDLproxy WSDL WSDLWSDLproxy Python server.methods keys()

SOAP getTemp WSDL

12.9.

>>>callInfo=server.methods['getTemp']

>>>callInfo.inparams

[<SOAPpy.wstools.WSDLTools.ParameterInfoinstanceat0x00CF3AD0>]

>>>callInfo.inparams[0].name

u'zipcode'

>>>callInfo.inparams[0].type

(u'http://www.w3.org/2001/XMLSchema',u'string')

server.methods SOAPpy CallInfo CallInfo

callInfo.inparams ParameterInfo Python ParameterInfo name SOAP SOAP Python WSDL.ProxyXMLSchemaXMLSchema zipcode WSDL.Proxy Python

WSDL

12.10.

>>>callInfo.outparams

[<SOAPpy.wstools.WSDLTools.ParameterInfoinstanceat0x00CF3AF8>]

>>>callInfo.outparams[0].name

u'return'

>>>callInfo.outparams[0].type

(u'http://www.w3.org/2001/XMLSchema',u'float')

callInfo.inparams callInfo.outparams SOAPPythonParameterInfo name type return

WSDLproxy SOAP

12.11. WSDLproxy SOAP

>>>fromSOAPpyimportWSDL

>>>wsdlFile='http://www.xmethods.net/sd/2001/TemperatureService.wsdl'

>>>server=WSDL.Proxy(wsdlFile)

>>>server.getTemp('90210')

66.0

>>>server.soapproxy.config.dumpSOAPOut=1

>>>server.soapproxy.config.dumpSOAPIn=1

>>>temperature=server.getTemp('90210')

***OutgoingSOAP******************************************************

<?xmlversion="1.0"encoding="UTF-8"?>

<SOAP-ENV:EnvelopeSOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"

xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"

xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance"

xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"

xmlns:xsd="http://www.w3.org/1999/XMLSchema">

<SOAP-ENV:Body>

<ns1:getTempxmlns:ns1="urn:xmethods-Temperature"SOAP-ENC:root="1">

<v1xsi:type="xsd:string">90210</v1>

</ns1:getTemp>

</SOAP-ENV:Body>

</SOAP-ENV:Envelope>

************************************************************************

***IncomingSOAP******************************************************

<?xmlversion='1.0'encoding='UTF-8'?>

<SOAP-ENV:Envelopexmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:xsd="http://www.w3.org/2001/XMLSchema">

<SOAP-ENV:Body>

<ns1:getTempResponsexmlns:ns1="urn:xmethods-Temperature"

SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">

<returnxsi:type="xsd:float">66.0</return>

</ns1:getTempResponse>

</SOAP-ENV:Body>

</SOAP-ENV:Envelope>

************************************************************************

>>>temperature

66.0

SOAP WSDL URL WSDL.Proxy WSDL SOAP SOAPProxyWSDL.Proxy SOAPProxy WSDL.Proxy SOAPProxy

server.soapproxy WSDL.Proxy SOAPProxy WSDLproxy SOAPProxyXML

<<WSDL 123456789 Google>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>SOAPWeb>Google <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

12.7.Google

Google SOAPAPIGoogleGoogle

12.4.Google

1. http://www.google.com/apis/E-mailE-mailGoogleAPIlicensekeyGoogle

2. http://www.google.com/apis/GoogleAPIskitPython WSDL

3. GoogleSearch.wsdl

Google WSDLGoogle

12.12.Google

>>>fromSOAPpyimportWSDL

>>>server=WSDL.Proxy('/path/to/your/GoogleSearch.wsdl')

>>>server.methods.keys()

[u'doGoogleSearch',u'doGetCachedPage',u'doSpellingSuggestion']

>>>callInfo=server.methods['doGoogleSearch']

>>>forargincallInfo.inparams:

...printarg.name.ljust(15),arg.type

key(u'http://www.w3.org/2001/XMLSchema',u'string')

q(u'http://www.w3.org/2001/XMLSchema',u'string')

start(u'http://www.w3.org/2001/XMLSchema',u'int')

maxResults(u'http://www.w3.org/2001/XMLSchema',u'int')

filter(u'http://www.w3.org/2001/XMLSchema',u'boolean')

restrict(u'http://www.w3.org/2001/XMLSchema',u'string')

safeSearch(u'http://www.w3.org/2001/XMLSchema',u'boolean')

lr(u'http://www.w3.org/2001/XMLSchema',u'string')

ie(u'http://www.w3.org/2001/XMLSchema',u'string')

oe(u'http://www.w3.org/2001/XMLSchema',u'string')

Google WSDL.ProxyGoogle WSDL WSDLGoogle doGoogleSearch,doGetCachedPagedoSpellingSuggestionGoogleGoogledoGoogleSearch WSDLGoogle WSDL WSDL.Proxy WSDL

doGoogleSearch

key——GoogleGoogleAPIq——Googlestart——Google10“ ” start10maxResults——10filter—— TrueGooglerestrict—— country countryUK linux macbsdGoogle unclesamsafeSearch—— TrueGooglelr(“”)——ieandoe(“”“ ”)—— utf-8

12.13.Google

>>>fromSOAPpyimportWSDL

>>>server=WSDL.Proxy('/path/to/your/GoogleSearch.wsdl')

>>>key='YOUR_GOOGLE_API_KEY'

>>>results=server.doGoogleSearch(key,'mark',0,10,False,"",

...False,"","utf-8","utf-8")

>>>len(results.resultElements)

10

>>>results.resultElements[0].URL

'http://diveintomark.org/'

>>>results.resultElements[0].title

'diveinto<b>mark</b>'

WSDL.Proxy server.doGoogleSearchGoogleGoogleAPI results.resultElements PythonresultElements URL title,snippetdir(results.resultElements[0]) Python WSDLproxy outparams

results10Google

12.14.Google

>>>results.searchTime

0.224919

>>>results.estimatedTotalResultsCount

29800000

>>>results.directoryCategories

[<SOAPpy.Types.structTypeitemat14367400>:

{'fullViewableName':

'Top/Arts/Literature/World_Literature/American/19th_Century/Twain,_Mark',

'specialEncoding':''}]

>>>results.directoryCategories[0].fullViewableName

'Top/Arts/Literature/World_Literature/American/19th_Century/Twain,_Mark'

0.224919 SOAPXMLGoogle30,000,00010 start server.doGoogleSearchGoogle GoogleDirectoryURLs

http://directory.google.com/directorycategory

<<WSDLSOAP 123456789 SOAP>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>SOAPWeb>SOAP <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

12.8.SOAPSOAP

SOAPHTTP SOAPHTTPXMLXML 11 HTTPWeb importhttplibhttplib.HTTPConnection.debuglevel=1HTTP

HTTP SOAPpy SOAP

SOAP

12.15.Proxy

>>>fromSOAPpyimportSOAPProxy

>>>url='http://services.xmethods.net:80/soap/servlet/rpcrouter'

>>>server=SOAPProxy(url)

>>>server.getTemp('27502')

<FaultSOAP-ENV:Server.BadTargetObjectURI:

Unabletodetermineobjectidfromcall:isthemethodelementnamespaced?>

Traceback(mostrecentcalllast):

File"<stdin>",line1,in?

File"c:\python23\Lib\site-packages\SOAPpy\Client.py",line453,in__call__

returnself.__r_call(*args,**kw)

File"c:\python23\Lib\site-packages\SOAPpy\Client.py",line475,in__r_call

self.__hd,self.__ma)

File"c:\python23\Lib\site-packages\SOAPpy\Client.py",line389,in__call

raisep

SOAPpy.Types.faultType:<FaultSOAP-ENV:Server.BadTargetObjectURI:

Unabletodetermineobjectidfromcall:isthemethodelementnamespaced?>

SOAPProxy URL URL

SOAP SOAPpySOAPpy.Types.faultType Python SOAP SOAP SOAP SOAPProxy

SOAP WSDL WSDL URL

12.16.

>>>wsdlFile='http://www.xmethods.net/sd/2001/TemperatureService.wsdl'

>>>server=WSDL.Proxy(wsdlFile)

>>>temperature=server.getTemp(27502)

<FaultSOAP-ENV:Server:Exceptionwhilehandlingservicerequest:

services.temperature.TempService.getTemp(int)--nosignaturematch>

Traceback(mostrecentcalllast):

File"<stdin>",line1,in?

File"c:\python23\Lib\site-packages\SOAPpy\Client.py",line453,in__call__

returnself.__r_call(*args,**kw)

File"c:\python23\Lib\site-packages\SOAPpy\Client.py",line475,in__r_call

self.__hd,self.__ma)

File"c:\python23\Lib\site-packages\SOAPpy\Client.py",line389,in__call

raisep

SOAPpy.Types.faultType:<FaultSOAP-ENV:Server:Exceptionwhilehandlingservicerequest:

services.temperature.TempService.getTemp(int)--nosignaturematch>

server.getTemp WSDL getTemp() SOAP zipcode WSDL.Proxy SOAP SOAP getTemp SOAPoverload SOAP WSDL.Proxy

Python

12.17.

>>>wsdlFile='http://www.xmethods.net/sd/2001/TemperatureService.wsdl'

>>>server=WSDL.Proxy(wsdlFile)

>>>(city,temperature)=server.getTemp(27502)

Traceback(mostrecentcalllast):

File"<stdin>",line1,in?

TypeError:unpacknon-sequence

server.getTemp SOAP SOAPWSDL.Proxy Python Python SOAP

Google

12.18.

>>>fromSOAPpyimportWSDL

>>>server=WSDL.Proxy(r'/path/to/local/GoogleSearch.wsdl')

>>>results=server.doGoogleSearch('foo','mark',0,10,False,""

...False,"","utf-8","utf-8")

<FaultSOAP-ENV:Server:

Exceptionfromserviceobject:Invalidauthorizationkey:foo:

<SOAPpy.Types.structTypedetailat14164616>:

{'stackTrace':

'com.google.soap.search.GoogleSearchFault:Invalidauthorizationkey:foo

atcom.google.soap.search.QueryLimits.lookUpAndLoadFromINSIfNeedBe(

QueryLimits.java:220)

atcom.google.soap.search.QueryLimits.validateKey(QueryLimits.java:127)

atcom.google.soap.search.GoogleSearchService.doPublicMethodChecks(

GoogleSearchService.java:825)

atcom.google.soap.search.GoogleSearchService.doGoogleSearch(

GoogleSearchService.java:121)

atsun.reflect.GeneratedMethodAccessor13.invoke(UnknownSource)

atsun.reflect.DelegatingMethodAccessorImpl.invoke(UnknownSource)

atjava.lang.reflect.Method.invoke(UnknownSource)

atorg.apache.soap.server.RPCRouter.invoke(RPCRouter.java:146)

atorg.apache.soap.providers.RPCJavaProvider.invoke(

RPCJavaProvider.java:129)

atorg.apache.soap.server.http.RPCRouterServlet.doPost(

RPCRouterServlet.java:288)

atjavax.servlet.http.HttpServlet.service(HttpServlet.java:760)

atjavax.servlet.http.HttpServlet.service(HttpServlet.java:853)

atcom.google.gse.HttpConnection.runServlet(HttpConnection.java:237)

atcom.google.gse.HttpConnection.run(HttpConnection.java:195)

atcom.google.gse.DispatchQueue$WorkerThread.run(DispatchQueue.java:201)

Causedby:com.google.soap.search.UserKeyInvalidException:Keywasofwrongsize.

atcom.google.soap.search.UserKey.<init>(UserKey.java:59)

atcom.google.soap.search.QueryLimits.lookUpAndLoadFromINSIfNeedBe(

QueryLimits.java:217)

...14more

'}>

Traceback(mostrecentcalllast):

File"<stdin>",line1,in?

File"c:\python23\Lib\site-packages\SOAPpy\Client.py",line453,in__call__

returnself.__r_call(*args,**kw)

File"c:\python23\Lib\site-packages\SOAPpy\Client.py",line475,in__r_call

self.__hd,self.__ma)

File"c:\python23\Lib\site-packages\SOAPpy\Client.py",line389,in__call

raisep

SOAPpy.Types.faultType:<FaultSOAP-ENV:Server:Exceptionfromserviceobject:

Invalidauthorizationkey:foo:

<SOAPpy.Types.structTypedetailat14164616>:

{'stackTrace':

'com.google.soap.search.GoogleSearchFault:Invalidauthorizationkey:foo

atcom.google.soap.search.QueryLimits.lookUpAndLoadFromINSIfNeedBe(

QueryLimits.java:220)

atcom.google.soap.search.QueryLimits.validateKey(QueryLimits.java:127)

atcom.google.soap.search.GoogleSearchService.doPublicMethodChecks(

GoogleSearchService.java:825)

atcom.google.soap.search.GoogleSearchService.doGoogleSearch(

GoogleSearchService.java:121)

atsun.reflect.GeneratedMethodAccessor13.invoke(UnknownSource)

atsun.reflect.DelegatingMethodAccessorImpl.invoke(UnknownSource)

atjava.lang.reflect.Method.invoke(UnknownSource)

atorg.apache.soap.server.RPCRouter.invoke(RPCRouter.java:146)

atorg.apache.soap.providers.RPCJavaProvider.invoke(

RPCJavaProvider.java:129)

atorg.apache.soap.server.http.RPCRouterServlet.doPost(

RPCRouterServlet.java:288)

atjavax.servlet.http.HttpServlet.service(HttpServlet.java:760)

atjavax.servlet.http.HttpServlet.service(HttpServlet.java:853)

atcom.google.gse.HttpConnection.runServlet(HttpConnection.java:237)

atcom.google.gse.HttpConnection.run(HttpConnection.java:195)

atcom.google.gse.DispatchQueue$WorkerThread.run(DispatchQueue.java:201)

Causedby:com.google.soap.search.UserKeyInvalidException:Keywasofwrongsize.

atcom.google.soap.search.UserKey.<init>(UserKey.java:59)

atcom.google.soap.search.QueryLimits.lookUpAndLoadFromINSIfNeedBe(

QueryLimits.java:217)

...14more

'}>

fooGoogleGoogle SOAPJava SOAP SOAP

fooInvalidauthorizationkey:foo

NewdevelopmentsforSOAPpy SOAP

<<Google 123456789 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>SOAPWeb> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

12.9.SOAP

SOAP WSDL SOAP SOAP

<<SOAP 123456789 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

13.2.(testsuite)

Python unittest

Python2.1 unittestPython2.0pyunit.sourceforge.net

"

"

(“ ,(checkin)...... ”)("")

<< 123456 romantest.py>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>>romantest.py <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

13.3. romantest.py

roman.py(testsuite)

13.1.romantest.py

,

"""Unittestforroman.py"""

importroman

importunittest

classKnownValues(unittest.TestCase):

knownValues=((1,'I'),

(2,'II'),

(3,'III'),

(4,'IV'),

(5,'V'),

(6,'VI'),

(7,'VII'),

(8,'VIII'),

(9,'IX'),

(10,'X'),

(50,'L'),

(100,'C'),

(500,'D'),

(1000,'M'),

(31,'XXXI'),

(148,'CXLVIII'),

(294,'CCXCIV'),

(312,'CCCXII'),

(421,'CDXXI'),

(528,'DXXVIII'),

(621,'DCXXI'),

(782,'DCCLXXXII'),

(870,'DCCCLXX'),

(941,'CMXLI'),

(1043,'MXLIII'),

(1110,'MCX'),

(1226,'MCCXXVI'),

(1301,'MCCCI'),

(1485,'MCDLXXXV'),

(1509,'MDIX'),

(1607,'MDCVII'),

(1754,'MDCCLIV'),

(1832,'MDCCCXXXII'),

(1993,'MCMXCIII'),

(2074,'MMLXXIV'),

(2152,'MMCLII'),

(2212,'MMCCXII'),

(2343,'MMCCCXLIII'),

(2499,'MMCDXCIX'),

(2574,'MMDLXXIV'),

(2646,'MMDCXLVI'),

(2723,'MMDCCXXIII'),

(2892,'MMDCCCXCII'),

(2975,'MMCMLXXV'),

(3051,'MMMLI'),

(3185,'MMMCLXXXV'),

(3250,'MMMCCL'),

(3313,'MMMCCCXIII'),

(3408,'MMMCDVIII'),

(3501,'MMMDI'),

(3610,'MMMDCX'),

(3743,'MMMDCCXLIII'),

(3844,'MMMDCCCXLIV'),

(3888,'MMMDCCCLXXXVIII'),

(3940,'MMMCMXL'),

(3999,'MMMCMXCIX'))

deftestToRomanKnownValues(self):

"""toRomanshouldgiveknownresultwithknowninput"""

forinteger,numeralinself.knownValues:

result=roman.toRoman(integer)

self.assertEqual(numeral,result)

deftestFromRomanKnownValues(self):

"""fromRomanshouldgiveknownresultwithknowninput"""

forinteger,numeralinself.knownValues:

result=roman.fromRoman(numeral)

self.assertEqual(integer,result)

classToRomanBadInput(unittest.TestCase):

deftestTooLarge(self):

"""toRomanshouldfailwithlargeinput"""

self.assertRaises(roman.OutOfRangeError,roman.toRoman,4000)

deftestZero(self):

"""toRomanshouldfailwith0input"""

self.assertRaises(roman.OutOfRangeError,roman.toRoman,0)

deftestNegative(self):

"""toRomanshouldfailwithnegativeinput"""

self.assertRaises(roman.OutOfRangeError,roman.toRoman,-1)

deftestNonInteger(self):

"""toRomanshouldfailwithnon-integerinput"""

self.assertRaises(roman.NotIntegerError,roman.toRoman,0.5)

classFromRomanBadInput(unittest.TestCase):

deftestTooManyRepeatedNumerals(self):

"""fromRomanshouldfailwithtoomanyrepeatednumerals"""

forsin('MMMM','DD','CCCC','LL','XXXX','VV','IIII'):

self.assertRaises(roman.InvalidRomanNumeralError,roman.fromRoman,s)

deftestRepeatedPairs(self):

"""fromRomanshouldfailwithrepeatedpairsofnumerals"""

forsin('CMCM','CDCD','XCXC','XLXL','IXIX','IVIV'):

self.assertRaises(roman.InvalidRomanNumeralError,roman.fromRoman,s)

deftestMalformedAntecedent(self):

"""fromRomanshouldfailwithmalformedantecedents"""

forsin('IIMXCC','VX','DCM','CMM','IXIV',

'MCMC','XCX','IVI','LM','LD','LC'):

self.assertRaises(roman.InvalidRomanNumeralError,roman.fromRoman,s)

classSanityCheck(unittest.TestCase):

deftestSanity(self):

"""fromRoman(toRoman(n))==nforalln"""

forintegerinrange(1,4000):

numeral=roman.toRoman(integer)

result=roman.fromRoman(numeral)

self.assertEqual(integer,result)

classCaseCheck(unittest.TestCase):

deftestToRomanCase(self):

"""toRomanshouldalwaysreturnuppercase"""

forintegerinrange(1,4000):

numeral=roman.toRoman(integer)

self.assertEqual(numeral,numeral.upper())

deftestFromRomanCase(self):

"""fromRomanshouldonlyacceptuppercaseinput"""

forintegerinrange(1,4000):

numeral=roman.toRoman(integer)

roman.fromRoman(numeral.upper())

self.assertRaises(roman.InvalidRomanNumeralError,

roman.fromRoman,numeral.lower())

if__name__=="__main__":

unittest.main()

PyUnit unittestPyUnitFAQ PythonLibraryReference unittestExtremeProgramming.orgThePortlandPatternRepository

<< 123456 Testingforsuccess>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>>Testingforsuccess <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

13.4.Testingforsuccesstestcase

1. toRoman 1 3999

13.2.testToRomanKnownValues

classKnownValues(unittest.TestCase):

knownValues=((1,'I'),

(2,'II'),

(3,'III'),

(4,'IV'),

(5,'V'),

(6,'VI'),

(7,'VII'),

(8,'VIII'),

(9,'IX'),

(10,'X'),

(50,'L'),

(100,'C'),

(500,'D'),

(1000,'M'),

(31,'XXXI'),

(148,'CXLVIII'),

(294,'CCXCIV'),

(312,'CCCXII'),

(421,'CDXXI'),

(528,'DXXVIII'),

(621,'DCXXI'),

(782,'DCCLXXXII'),

(870,'DCCCLXX'),

(941,'CMXLI'),

(1043,'MXLIII'),

(1110,'MCX'),

(1226,'MCCXXVI'),

(1301,'MCCCI'),

(1485,'MCDLXXXV'),

(1509,'MDIX'),

(1607,'MDCVII'),

(1754,'MDCCLIV'),

(1832,'MDCCCXXXII'),

(1993,'MCMXCIII'),

(2074,'MMLXXIV'),

(2152,'MMCLII'),

(2212,'MMCCXII'),

(2343,'MMCCCXLIII'),

(2499,'MMCDXCIX'),

(2574,'MMDLXXIV'),

(2646,'MMDCXLVI'),

(2723,'MMDCCXXIII'),

(2892,'MMDCCCXCII'),

(2975,'MMCMLXXV'),

(3051,'MMMLI'),

(3185,'MMMCLXXXV'),

(3250,'MMMCCL'),

(3313,'MMMCCCXIII'),

(3408,'MMMCDVIII'),

(3501,'MMMDI'),

(3610,'MMMDCX'),

(3743,'MMMDCCXLIII'),

(3844,'MMMDCCCXLIV'),

(3888,'MMMDCCCLXXXVIII'),

(3940,'MMMCMXL'),

(3999,'MMMCMXCIX'))

deftestToRomanKnownValues(self):

"""toRomanshouldgiveknownresultwithknowninput"""

forinteger,numeralinself.knownValues:

result=roman.toRoman(integer)

self.assertEqual(numeral,result)

unittest TestCase TestCaseinteger/numeral

toRoman toRoman API API" toRoman toRoman toRoman

toRoman TestCase assertEqualtoRoman( value)( numeral) assertEqual

assertEqual toRoman assertEqualtestToRomanKnownValues toRoman

<<romantest.py 123456 Testingforfailure>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>>Testingforfailure <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

13.5.Testingforfailure

toRoman

2. toRoman 1to39993. toRoman

Python unittest

13.3. toRoman

classToRomanBadInput(unittest.TestCase):

deftestTooLarge(self):

"""toRomanshouldfailwithlargeinput"""

self.assertRaises(roman.OutOfRangeError,roman.toRoman,4000)

deftestZero(self):

"""toRomanshouldfailwith0input"""

self.assertRaises(roman.OutOfRangeError,roman.toRoman,0)

deftestNegative(self):

"""toRomanshouldfailwithnegativeinput"""

self.assertRaises(roman.OutOfRangeError,roman.toRoman,-1)

deftestNonInteger(self):

"""toRomanshouldfailwithnon-integerinput"""

self.assertRaises(roman.NotIntegerError,roman.toRoman,0.5)

unittest TestCase assertRaisesassertRaises toRoman try...exceptblock assertRaises roman.OutOfRangeError toRoman

toRoman4000 assertRaises toRomanroman.OutOfRangeError toRomanPython 0 testZero testNegative testZerotoRoman 0 roman.OutOfRangeError roman.OutOfRangeError#3 toRoman toRoman 0.5 roman.NotIntegerError toRoman roman.NotIntegerError

fromRoman toRoman

4. fromRoman5. fromRoman

#4 #1 #5#2#3 fromRoman

13.4. fromRoman

classFromRomanBadInput(unittest.TestCase):

deftestTooManyRepeatedNumerals(self):

"""fromRomanshouldfailwithtoomanyrepeatednumerals"""

forsin('MMMM','DD','CCCC','LL','XXXX','VV','IIII'):

self.assertRaises(roman.InvalidRomanNumeralError,roman.fromRoman,s)

deftestRepeatedPairs(self):

"""fromRomanshouldfailwithrepeatedpairsofnumerals"""

forsin('CMCM','CDCD','XCXC','XLXL','IXIX','IVIV'):

self.assertRaises(roman.InvalidRomanNumeralError,roman.fromRoman,s)

deftestMalformedAntecedent(self):

"""fromRomanshouldfailwithmalformedantecedents"""

forsin('IIMXCC','VX','DCM','CMM','IXIV',

'MCMC','XCX','IVI','LM','LD','LC'):

self.assertRaises(roman.InvalidRomanNumeralError,roman.fromRoman,s)

toRoman roman.InvalidRomanNumeralError

roman.py roman.OutOfRangeErrorroman.NotIntegerError roman.py

<<Testingforsuccess 123456 Testingforsanity>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>>Testingforsanity <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

13.6.TestingforsanityABBA“ ”ABA

6. 1..3999n fromRoman(toRoman(n))==n

13.5. toRoman fromRoman

classSanityCheck(unittest.TestCase):

deftestSanity(self):

"""fromRoman(toRoman(n))==nforalln"""

forintegerinrange(1,4000):

numeral=roman.toRoman(integer)

result=roman.fromRoman(numeral)

self.assertEqual(integer,result)

range 14000 1..3999 integer Python integernumeral result assertEqual assertEqual testSanity

7. toRoman8. fromRoman

fromRoman toRoman fromRoman“ ”#6"

13.6.

classCaseCheck(unittest.TestCase):

deftestToRomanCase(self):

"""toRomanshouldalwaysreturnuppercase"""

forintegerinrange(1,4000):

numeral=roman.toRoman(integer)

self.assertEqual(numeral,numeral.upper())

deftestFromRomanCase(self):

"""fromRomanshouldonlyacceptuppercaseinput"""

forintegerinrange(1,4000):

numeral=roman.toRoman(integer)

roman.fromRoman(numeral.upper())

self.assertRaises(roman.InvalidRomanNumeralError,

roman.fromRoman,numeral.lower())

toRoman toRoman[6]

“ ”toRoman fromRoman toRoman testToRomanCase “” fromRoman Python PythonfromRoman ToRomanBadInput FromRomanBadInput

roman.fromRoman roman.InvalidRomanNumeralError

Footnotes

[6]“Icanresisteverythingexcepttemptation. ”--OscarWilde

<<Testingforfailure 123456 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

1414.1.roman.py,114.2.roman.py,214.3.roman.py,314.4.roman.py,414.5.roman.py,5

14.1.roman.py,1

roman.py

14.1.roman1.py

py/roman/stage1/

,

"""ConverttoandfromRomannumerals"""

#Defineexceptions

classRomanError(Exception):pass

classOutOfRangeError(RomanError):pass

classNotIntegerError(RomanError):pass

classInvalidRomanNumeralError(RomanError):pass

deftoRoman(n):

"""convertintegertoRomannumeral"""

pass

deffromRoman(s):

"""convertRomannumeraltointeger"""

pass

Python ExceptionRomanError Exception ExceptionOutOfRangeError NotIntegerError toRomanToRomanBadInputInvalidRomanNumeralError fromRomanFromRomanBadInput

API Python pass

romantest.py

romantest1.py -v

14.2.Outputofromantest1.pyagainstroman1.py

fromRomanshouldonlyacceptuppercaseinput...ERROR

toRomanshouldalwaysreturnuppercase...ERROR

fromRomanshouldfailwithmalformedantecedents...FAIL

fromRomanshouldfailwithrepeatedpairsofnumerals...FAIL

fromRomanshouldfailwithtoomanyrepeatednumerals...FAIL

fromRomanshouldgiveknownresultwithknowninput...FAIL

toRomanshouldgiveknownresultwithknowninput...FAIL

fromRoman(toRoman(n))==nforalln...FAIL

toRomanshouldfailwithnon-integerinput...FAIL

toRomanshouldfailwithnegativeinput...FAIL

toRomanshouldfailwithlargeinput...FAIL

toRomanshouldfailwith0input...FAIL

======================================================================

ERROR:fromRomanshouldonlyacceptuppercaseinput

----------------------------------------------------------------------

Traceback(mostrecentcalllast):

File"C:\docbook\dip\py\roman\stage1\romantest1.py",line154,intestFromRomanCase

roman1.fromRoman(numeral.upper())

AttributeError:'None'objecthasnoattribute'upper'

======================================================================

ERROR:toRomanshouldalwaysreturnuppercase

----------------------------------------------------------------------

Traceback(mostrecentcalllast):

File"C:\docbook\dip\py\roman\stage1\romantest1.py",line148,intestToRomanCase

self.assertEqual(numeral,numeral.upper())

AttributeError:'None'objecthasnoattribute'upper'

======================================================================

FAIL:fromRomanshouldfailwithmalformedantecedents

----------------------------------------------------------------------

Traceback(mostrecentcalllast):

File"C:\docbook\dip\py\roman\stage1\romantest1.py",line133,intestMalformedAntecedent

self.assertRaises(roman1.InvalidRomanNumeralError,roman1.fromRoman,s)

File"c:\python21\lib\unittest.py",line266,infailUnlessRaises

raiseself.failureException,excName

AssertionError:InvalidRomanNumeralError

======================================================================

FAIL:fromRomanshouldfailwithrepeatedpairsofnumerals

----------------------------------------------------------------------

Traceback(mostrecentcalllast):

File"C:\docbook\dip\py\roman\stage1\romantest1.py",line127,intestRepeatedPairs

self.assertRaises(roman1.InvalidRomanNumeralError,roman1.fromRoman,s)

File"c:\python21\lib\unittest.py",line266,infailUnlessRaises

raiseself.failureException,excName

AssertionError:InvalidRomanNumeralError

======================================================================

FAIL:fromRomanshouldfailwithtoomanyrepeatednumerals

----------------------------------------------------------------------

Traceback(mostrecentcalllast):

File"C:\docbook\dip\py\roman\stage1\romantest1.py",line122,intestTooManyRepeatedNumerals

self.assertRaises(roman1.InvalidRomanNumeralError,roman1.fromRoman,s)

File"c:\python21\lib\unittest.py",line266,infailUnlessRaises

raiseself.failureException,excName

AssertionError:InvalidRomanNumeralError

======================================================================

FAIL:fromRomanshouldgiveknownresultwithknowninput

----------------------------------------------------------------------

Traceback(mostrecentcalllast):

File"C:\docbook\dip\py\roman\stage1\romantest1.py",line99,intestFromRomanKnownValues

self.assertEqual(integer,result)

File"c:\python21\lib\unittest.py",line273,infailUnlessEqual

raiseself.failureException,(msgor'%s!=%s'%(first,second))

AssertionError:1!=None

======================================================================

FAIL:toRomanshouldgiveknownresultwithknowninput

----------------------------------------------------------------------

Traceback(mostrecentcalllast):

File"C:\docbook\dip\py\roman\stage1\romantest1.py",line93,intestToRomanKnownValues

self.assertEqual(numeral,result)

File"c:\python21\lib\unittest.py",line273,infailUnlessEqual

raiseself.failureException,(msgor'%s!=%s'%(first,second))

AssertionError:I!=None

======================================================================

FAIL:fromRoman(toRoman(n))==nforalln

----------------------------------------------------------------------

Traceback(mostrecentcalllast):

File"C:\docbook\dip\py\roman\stage1\romantest1.py",line141,intestSanity

self.assertEqual(integer,result)

File"c:\python21\lib\unittest.py",line273,infailUnlessEqual

raiseself.failureException,(msgor'%s!=%s'%(first,second))

AssertionError:1!=None

======================================================================

FAIL:toRomanshouldfailwithnon-integerinput

----------------------------------------------------------------------

Traceback(mostrecentcalllast):

File"C:\docbook\dip\py\roman\stage1\romantest1.py",line116,intestNonInteger

self.assertRaises(roman1.NotIntegerError,roman1.toRoman,0.5)

File"c:\python21\lib\unittest.py",line266,infailUnlessRaises

raiseself.failureException,excName

AssertionError:NotIntegerError

======================================================================

FAIL:toRomanshouldfailwithnegativeinput

----------------------------------------------------------------------

Traceback(mostrecentcalllast):

File"C:\docbook\dip\py\roman\stage1\romantest1.py",line112,intestNegative

self.assertRaises(roman1.OutOfRangeError,roman1.toRoman,-1)

File"c:\python21\lib\unittest.py",line266,infailUnlessRaises

raiseself.failureException,excName

AssertionError:OutOfRangeError

======================================================================

FAIL:toRomanshouldfailwithlargeinput

----------------------------------------------------------------------

Traceback(mostrecentcalllast):

File"C:\docbook\dip\py\roman\stage1\romantest1.py",line104,intestTooLarge

self.assertRaises(roman1.OutOfRangeError,roman1.toRoman,4000)

File"c:\python21\lib\unittest.py",line266,infailUnlessRaises

raiseself.failureException,excName

AssertionError:OutOfRangeError

======================================================================

FAIL:toRomanshouldfailwith0input

----------------------------------------------------------------------

Traceback(mostrecentcalllast):

File"C:\docbook\dip\py\roman\stage1\romantest1.py",line108,intestZero

self.assertRaises(roman1.OutOfRangeError,roman1.toRoman,0)

File"c:\python21\lib\unittest.py",line266,infailUnlessRaises

raiseself.failureException,excName

AssertionError:OutOfRangeError

----------------------------------------------------------------------

Ran12testsin0.040s

FAILED(failures=10,errors=2)

unittest.main() romantest.py doc

string unittest assertRaises failUnlessRaises

AssertionError toRoman OutOfRangeError unittest unittestfailureserrors assertXYZ

assertEqual assertRaisestestFromRomanCase“ fromRoman” numeral.upper()

AttributeError toRoman testZero“ toRoman0 ” fromRoman assertRaisesInvalidRomanNumeral

<<Testingforsanity 12345 roman.py,2>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>>roman.py,2 <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

14.2.roman.py,2

roman

14.3.roman2.py

py/roman/stage2/

,

"""ConverttoandfromRomannumerals"""

#Defineexceptions

classRomanError(Exception):pass

classOutOfRangeError(RomanError):pass

classNotIntegerError(RomanError):pass

classInvalidRomanNumeralError(RomanError):pass

#Definedigitmapping

romanNumeralMap=(('M',1000),

('CM',900),

('D',500),

('CD',400),

('C',100),

('XC',90),

('L',50),

('XL',40),

('X',10),

('IX',9),

('V',5),

('IV',4),

('I',1))

deftoRoman(n):

"""convertintegertoRomannumeral"""

result=""

fornumeral,integerinromanNumeralMap:

whilen>=integer:

result+=numeral

n-=integer

returnresult

deffromRoman(s):

"""convertRomannumeraltointeger"""

pass

romanNumeralMap

1. CM“ 900 ” toRoman

2. M I

3. numeral value

romanNumeralMap

14.4.toRoman

toRoman while print

whilen>=integer:

result+=numeral

n-=integer

print'subtracting',integer,'frominput,adding',numeral,

>>>importroman2

>>>roman2.toRoman(1424)

subtracting1000frominput,addingMtooutput

subtracting400frominput,addingCDtooutput

subtracting10frominput,addingXtooutput

subtracting10frominput,addingXtooutput

subtracting4frominput,addingIVtooutput

'MCDXXIV'

toRoman

14.5. romantest2.py roman2.py

romantest2.py -v

fromRomanshouldonlyacceptuppercaseinput...FAIL

toRomanshouldalwaysreturnuppercase...ok

fromRomanshouldfailwithmalformedantecedents...FAIL

fromRomanshouldfailwithrepeatedpairsofnumerals...FAIL

fromRomanshouldfailwithtoomanyrepeatednumerals...FAIL

fromRomanshouldgiveknownresultwithknowninput...FAIL

toRomanshouldgiveknownresultwithknowninput...ok

fromRoman(toRoman(n))==nforalln...FAIL

toRomanshouldfailwithnon-integerinput...FAIL

toRomanshouldfailwithnegativeinput...FAIL

toRomanshouldfailwithlargeinput...FAIL

toRomanshouldfailwith0input...FAIL

toRoman romanNumeralMap toRoman 3999 3888

“ ” assertRaises

10

======================================================================

FAIL:fromRomanshouldonlyacceptuppercaseinput

----------------------------------------------------------------------

Traceback(mostrecentcalllast):

File"C:\docbook\dip\py\roman\stage2\romantest2.py",line156,intestFromRomanCase

roman2.fromRoman,numeral.lower())

File"c:\python21\lib\unittest.py",line266,infailUnlessRaises

raiseself.failureException,excName

AssertionError:InvalidRomanNumeralError

======================================================================

FAIL:fromRomanshouldfailwithmalformedantecedents

----------------------------------------------------------------------

Traceback(mostrecentcalllast):

File"C:\docbook\dip\py\roman\stage2\romantest2.py",line133,intestMalformedAntecedent

self.assertRaises(roman2.InvalidRomanNumeralError,roman2.fromRoman,s)

File"c:\python21\lib\unittest.py",line266,infailUnlessRaises

raiseself.failureException,excName

AssertionError:InvalidRomanNumeralError

======================================================================

FAIL:fromRomanshouldfailwithrepeatedpairsofnumerals

----------------------------------------------------------------------

Traceback(mostrecentcalllast):

File"C:\docbook\dip\py\roman\stage2\romantest2.py",line127,intestRepeatedPairs

self.assertRaises(roman2.InvalidRomanNumeralError,roman2.fromRoman,s)

File"c:\python21\lib\unittest.py",line266,infailUnlessRaises

raiseself.failureException,excName

AssertionError:InvalidRomanNumeralError

======================================================================

FAIL:fromRomanshouldfailwithtoomanyrepeatednumerals

----------------------------------------------------------------------

Traceback(mostrecentcalllast):

File"C:\docbook\dip\py\roman\stage2\romantest2.py",line122,intestTooManyRepeatedNumerals

self.assertRaises(roman2.InvalidRomanNumeralError,roman2.fromRoman,s)

File"c:\python21\lib\unittest.py",line266,infailUnlessRaises

raiseself.failureException,excName

AssertionError:InvalidRomanNumeralError

======================================================================

FAIL:fromRomanshouldgiveknownresultwithknowninput

----------------------------------------------------------------------

Traceback(mostrecentcalllast):

File"C:\docbook\dip\py\roman\stage2\romantest2.py",line99,intestFromRomanKnownValues

self.assertEqual(integer,result)

File"c:\python21\lib\unittest.py",line273,infailUnlessEqual

raiseself.failureException,(msgor'%s!=%s'%(first,second))

AssertionError:1!=None

======================================================================

FAIL:fromRoman(toRoman(n))==nforalln

----------------------------------------------------------------------

Traceback(mostrecentcalllast):

File"C:\docbook\dip\py\roman\stage2\romantest2.py",line141,intestSanity

self.assertEqual(integer,result)

File"c:\python21\lib\unittest.py",line273,infailUnlessEqual

raiseself.failureException,(msgor'%s!=%s'%(first,second))

AssertionError:1!=None

======================================================================

FAIL:toRomanshouldfailwithnon-integerinput

----------------------------------------------------------------------

Traceback(mostrecentcalllast):

File"C:\docbook\dip\py\roman\stage2\romantest2.py",line116,intestNonInteger

self.assertRaises(roman2.NotIntegerError,roman2.toRoman,0.5)

File"c:\python21\lib\unittest.py",line266,infailUnlessRaises

raiseself.failureException,excName

AssertionError:NotIntegerError

======================================================================

FAIL:toRomanshouldfailwithnegativeinput

----------------------------------------------------------------------

Traceback(mostrecentcalllast):

File"C:\docbook\dip\py\roman\stage2\romantest2.py",line112,intestNegative

self.assertRaises(roman2.OutOfRangeError,roman2.toRoman,-1)

File"c:\python21\lib\unittest.py",line266,infailUnlessRaises

raiseself.failureException,excName

AssertionError:OutOfRangeError

======================================================================

FAIL:toRomanshouldfailwithlargeinput

----------------------------------------------------------------------

Traceback(mostrecentcalllast):

File"C:\docbook\dip\py\roman\stage2\romantest2.py",line104,intestTooLarge

self.assertRaises(roman2.OutOfRangeError,roman2.toRoman,4000)

File"c:\python21\lib\unittest.py",line266,infailUnlessRaises

raiseself.failureException,excName

AssertionError:OutOfRangeError

======================================================================

FAIL:toRomanshouldfailwith0input

----------------------------------------------------------------------

Traceback(mostrecentcalllast):

File"C:\docbook\dip\py\roman\stage2\romantest2.py",line108,intestZero

self.assertRaises(roman2.OutOfRangeError,roman2.toRoman,0)

File"c:\python21\lib\unittest.py",line266,infailUnlessRaises

raiseself.failureException,excName

AssertionError:OutOfRangeError

----------------------------------------------------------------------

Ran12testsin0.320s

FAILED(failures=10)

<< 12345 roman.py,3>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>>roman.py,3 <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

14.3.roman.py,3

toRoman1 3999

14.6.roman3.py

py/roman/stage3/

,

"""ConverttoandfromRomannumerals"""

#Defineexceptions

classRomanError(Exception):pass

classOutOfRangeError(RomanError):pass

classNotIntegerError(RomanError):pass

classInvalidRomanNumeralError(RomanError):pass

#Definedigitmapping

romanNumeralMap=(('M',1000),

('CM',900),

('D',500),

('CD',400),

('C',100),

('XC',90),

('L',50),

('XL',40),

('X',10),

('IX',9),

('V',5),

('IV',4),

('I',1))

deftoRoman(n):

"""convertintegertoRomannumeral"""

ifnot(0<n<4000):

raiseOutOfRangeError,"numberoutofrange(mustbe1..3999)"

ifint(n)<>n:

raiseNotIntegerError,"non-integerscannotbeconverted"

result=""

fornumeral,integerinromanNumeralMap:

whilen>=integer:

result+=numeral

n-=integer

returnresult

deffromRoman(s):

"""convertRomannumeraltointeger"""

pass

Pythonic ifnot((0<n)and(n<4000))

raisetrackback

14.7. toRoman

>>>importroman3

>>>roman3.toRoman(4000)

Traceback(mostrecentcalllast):

File"<interactiveinput>",line1,in?

File"roman3.py",line27,intoRoman

raiseOutOfRangeError,"numberoutofrange(mustbe1..3999)"

OutOfRangeError:numberoutofrange(mustbe1..3999)

>>>roman3.toRoman(1.5)

Traceback(mostrecentcalllast):

File"<interactiveinput>",line1,in?

File"roman3.py",line29,intoRoman

raiseNotIntegerError,"non-integerscannotbeconverted"

NotIntegerError:non-integerscannotbeconverted

14.8. romantest3.py roman3.py

fromRomanshouldonlyacceptuppercaseinput...FAIL

toRomanshouldalwaysreturnuppercase...ok

fromRomanshouldfailwithmalformedantecedents...FAIL

fromRomanshouldfailwithrepeatedpairsofnumerals...FAIL

fromRomanshouldfailwithtoomanyrepeatednumerals...FAIL

fromRomanshouldgiveknownresultwithknowninput...FAIL

toRomanshouldgiveknownresultwithknowninput...ok

fromRoman(toRoman(n))==nforalln...FAIL

toRomanshouldfailwithnon-integerinput...ok

toRomanshouldfailwithnegativeinput...ok

toRomanshouldfailwithlargeinput...ok

toRomanshouldfailwith0input...ok

toRoman 2 testNonInteger int(n)<>n toRoman

int(n)<>n NotIntegerError testNonIntegertestNegative not(0<n<4000) testNegativeOutOfRangeError

======================================================================

FAIL:fromRomanshouldonlyacceptuppercaseinput

----------------------------------------------------------------------

Traceback(mostrecentcalllast):

File"C:\docbook\dip\py\roman\stage3\romantest3.py",line156,intestFromRomanCase

roman3.fromRoman,numeral.lower())

File"c:\python21\lib\unittest.py",line266,infailUnlessRaises

raiseself.failureException,excName

AssertionError:InvalidRomanNumeralError

======================================================================

FAIL:fromRomanshouldfailwithmalformedantecedents

----------------------------------------------------------------------

Traceback(mostrecentcalllast):

File"C:\docbook\dip\py\roman\stage3\romantest3.py",line133,intestMalformedAntecedent

self.assertRaises(roman3.InvalidRomanNumeralError,roman3.fromRoman,s)

File"c:\python21\lib\unittest.py",line266,infailUnlessRaises

raiseself.failureException,excName

AssertionError:InvalidRomanNumeralError

======================================================================

FAIL:fromRomanshouldfailwithrepeatedpairsofnumerals

----------------------------------------------------------------------

Traceback(mostrecentcalllast):

File"C:\docbook\dip\py\roman\stage3\romantest3.py",line127,intestRepeatedPairs

self.assertRaises(roman3.InvalidRomanNumeralError,roman3.fromRoman,s)

File"c:\python21\lib\unittest.py",line266,infailUnlessRaises

raiseself.failureException,excName

AssertionError:InvalidRomanNumeralError

======================================================================

FAIL:fromRomanshouldfailwithtoomanyrepeatednumerals

----------------------------------------------------------------------

Traceback(mostrecentcalllast):

File"C:\docbook\dip\py\roman\stage3\romantest3.py",line122,intestTooManyRepeatedNumerals

self.assertRaises(roman3.InvalidRomanNumeralError,roman3.fromRoman,s)

File"c:\python21\lib\unittest.py",line266,infailUnlessRaises

raiseself.failureException,excName

AssertionError:InvalidRomanNumeralError

======================================================================

FAIL:fromRomanshouldgiveknownresultwithknowninput

----------------------------------------------------------------------

Traceback(mostrecentcalllast):

File"C:\docbook\dip\py\roman\stage3\romantest3.py",line99,intestFromRomanKnownValues

self.assertEqual(integer,result)

File"c:\python21\lib\unittest.py",line273,infailUnlessEqual

raiseself.failureException,(msgor'%s!=%s'%(first,second))

AssertionError:1!=None

======================================================================

FAIL:fromRoman(toRoman(n))==nforalln

----------------------------------------------------------------------

Traceback(mostrecentcalllast):

File"C:\docbook\dip\py\roman\stage3\romantest3.py",line141,intestSanity

self.assertEqual(integer,result)

File"c:\python21\lib\unittest.py",line273,infailUnlessEqual

raiseself.failureException,(msgor'%s!=%s'%(first,second))

AssertionError:1!=None

----------------------------------------------------------------------

Ran12testsin0.401s

FAILED(failures=6)

6 fromRoman toRoman fromRoman toRoman“ ”

<<roman.py,2 12345 roman.py,4>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>>roman.py,4 <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

14.4.roman.py,4

toRoman fromRoman toRoman

14.9.roman4.py

py/roman/stage4/

,

"""ConverttoandfromRomannumerals"""

#Defineexceptions

classRomanError(Exception):pass

classOutOfRangeError(RomanError):pass

classNotIntegerError(RomanError):pass

classInvalidRomanNumeralError(RomanError):pass

#Definedigitmapping

romanNumeralMap=(('M',1000),

('CM',900),

('D',500),

('CD',400),

('C',100),

('XC',90),

('L',50),

('XL',40),

('X',10),

('IX',9),

('V',5),

('IV',4),

('I',1))

#toRomanfunctionomittedforclarity(ithasn'tchanged)

deffromRoman(s):

"""convertRomannumeraltointeger"""

result=0

index=0

fornumeral,integerinromanNumeralMap:

whiles[index:index+len(numeral)]==numeral:

result+=integer

index+=len(numeral)

returnresult

toRoman“ ”

14.10.fromRoman

fromRoman while print

whiles[index:index+len(numeral)]==numeral:

result+=integer

index+=len(numeral)

print'found',numeral,'oflength',len(numeral),',adding'

>>>importroman4

>>>roman4.fromRoman('MCMLXXII')

foundM,oflength1,adding1000

foundCM,oflength2,adding900

foundL,oflength1,adding50

foundX,oflength1,adding10

foundX,oflength1,adding10

foundI,oflength1,adding1

foundI,oflength1,adding1

1972

14.11. romantest4.py roman4.py

fromRomanshouldonlyacceptuppercaseinput...FAIL

toRomanshouldalwaysreturnuppercase...ok

fromRomanshouldfailwithmalformedantecedents...FAIL

fromRomanshouldfailwithrepeatedpairsofnumerals...FAIL

fromRomanshouldfailwithtoomanyrepeatednumerals...FAIL

fromRomanshouldgiveknownresultwithknowninput...ok

toRomanshouldgiveknownresultwithknowninput...ok

fromRoman(toRoman(n))==nforalln...ok

toRomanshouldfailwithnon-integerinput...ok

toRomanshouldfailwithnegativeinput...ok

toRomanshouldfailwithlargeinput...ok

toRomanshouldfailwith0input...ok

fromRoman toRoman fromRoman toRomanfromRoman toRoman

======================================================================

FAIL:fromRomanshouldonlyacceptuppercaseinput

----------------------------------------------------------------------

Traceback(mostrecentcalllast):

File"C:\docbook\dip\py\roman\stage4\romantest4.py",line156,intestFromRomanCase

roman4.fromRoman,numeral.lower())

File"c:\python21\lib\unittest.py",line266,infailUnlessRaises

raiseself.failureException,excName

AssertionError:InvalidRomanNumeralError

======================================================================

FAIL:fromRomanshouldfailwithmalformedantecedents

----------------------------------------------------------------------

Traceback(mostrecentcalllast):

File"C:\docbook\dip\py\roman\stage4\romantest4.py",line133,intestMalformedAntecedent

self.assertRaises(roman4.InvalidRomanNumeralError,roman4.fromRoman,s)

File"c:\python21\lib\unittest.py",line266,infailUnlessRaises

raiseself.failureException,excName

AssertionError:InvalidRomanNumeralError

======================================================================

FAIL:fromRomanshouldfailwithrepeatedpairsofnumerals

----------------------------------------------------------------------

Traceback(mostrecentcalllast):

File"C:\docbook\dip\py\roman\stage4\romantest4.py",line127,intestRepeatedPairs

self.assertRaises(roman4.InvalidRomanNumeralError,roman4.fromRoman,s)

File"c:\python21\lib\unittest.py",line266,infailUnlessRaises

raiseself.failureException,excName

AssertionError:InvalidRomanNumeralError

======================================================================

FAIL:fromRomanshouldfailwithtoomanyrepeatednumerals

----------------------------------------------------------------------

Traceback(mostrecentcalllast):

File"C:\docbook\dip\py\roman\stage4\romantest4.py",line122,intestTooManyRepeatedNumerals

self.assertRaises(roman4.InvalidRomanNumeralError,roman4.fromRoman,s)

File"c:\python21\lib\unittest.py",line266,infailUnlessRaises

raiseself.failureException,excName

AssertionError:InvalidRomanNumeralError

----------------------------------------------------------------------

Ran12testsin1.222s

FAILED(failures=4)

<<roman.py,3 12345 roman.py,5>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>>roman.py,5 <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

14.5.roman.py,5

fromRoman toRoman

7

7.3“” M D C L X V I

1. “” I 1 II 2 III 3 VI 6“ 5 1”) VII 7

VIII 8

2. I X C M 45 4 IIII IV“ 5 1” 40

XL“ 50 10” 41 XLI 42 XLII 43 XLIII 44 XLIV“ 5010 5 1”)

3. 910 8 VIII 9 IX“ 10 1” VIIII I 90 XC 900 CM

4. 10 X VV 100 C LL

5. DC 600 CD 400“ 500 100”) CI 101 IC1001 XCIX“ 100 10 9 10 1”

14.12.roman5.py

py/roman/stage5/

,

"""ConverttoandfromRomannumerals"""

importre

#Defineexceptions

classRomanError(Exception):pass

classOutOfRangeError(RomanError):pass

classNotIntegerError(RomanError):pass

classInvalidRomanNumeralError(RomanError):pass

#Definedigitmapping

romanNumeralMap=(('M',1000),

('CM',900),

('D',500),

('CD',400),

('C',100),

('XC',90),

('L',50),

('XL',40),

('X',10),

('IX',9),

('V',5),

('IV',4),

('I',1))

deftoRoman(n):

"""convertintegertoRomannumeral"""

ifnot(0<n<4000):

raiseOutOfRangeError,"numberoutofrange(mustbe1..3999)"

ifint(n)<>n:

raiseNotIntegerError,"non-integerscannotbeconverted"

result=""

fornumeral,integerinromanNumeralMap:

whilen>=integer:

result+=numeral

n-=integer

returnresult

#DefinepatterntodetectvalidRomannumerals

romanNumeralPattern='^M?M?M?(CM|CD|D?C?C?C?)(XC|XL|L?X?X?X?)(IX|IV|V?I?I?I?)$'

deffromRoman(s):

"""convertRomannumeraltointeger"""

ifnotre.search(romanNumeralPattern,s):

raiseInvalidRomanNumeralError,'InvalidRomannumeral:%s'

result=0

index=0

fornumeral,integerinromanNumeralMap:

whiles[index:index+len(numeral)]==numeral:

result+=integer

index+=len(numeral)

returnresult

7.3“” XC90 XL40 L03 X IX9 IV4 V03 I re.search

14.13. romantest5.py roman5.py

fromRomanshouldonlyacceptuppercaseinput...ok

toRomanshouldalwaysreturnuppercase...ok

fromRomanshouldfailwithmalformedantecedents...ok

fromRomanshouldfailwithrepeatedpairsofnumerals...ok

fromRomanshouldfailwithtoomanyrepeatednumerals...ok

fromRomanshouldgiveknownresultwithknowninput...ok

toRomanshouldgiveknownresultwithknowninput...ok

fromRoman(toRoman(n))==nforalln...ok

toRomanshouldfailwithnon-integerinput...ok

toRomanshouldfailwithnegativeinput...ok

toRomanshouldfailwithlargeinput...ok

toRomanshouldfailwith0input...ok

----------------------------------------------------------------------

Ran12testsin2.864s

OK

romanNumeralPattern re.search MCMC fromRomanInvalidRomanNumeralError“ OK”“” unittest

<<roman.py,4 12345 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

15.2.

4 M 4000 1..3999 1..4999

15.6. romantest71.py

py/roman/stage7/

,

importroman71

importunittest

classKnownValues(unittest.TestCase):

knownValues=((1,'I'),

(2,'II'),

(3,'III'),

(4,'IV'),

(5,'V'),

(6,'VI'),

(7,'VII'),

(8,'VIII'),

(9,'IX'),

(10,'X'),

(50,'L'),

(100,'C'),

(500,'D'),

(1000,'M'),

(31,'XXXI'),

(148,'CXLVIII'),

(294,'CCXCIV'),

(312,'CCCXII'),

(421,'CDXXI'),

(528,'DXXVIII'),

(621,'DCXXI'),

(782,'DCCLXXXII'),

(870,'DCCCLXX'),

(941,'CMXLI'),

(1043,'MXLIII'),

(1110,'MCX'),

(1226,'MCCXXVI'),

(1301,'MCCCI'),

(1485,'MCDLXXXV'),

(1509,'MDIX'),

(1607,'MDCVII'),

(1754,'MDCCLIV'),

(1832,'MDCCCXXXII'),

(1993,'MCMXCIII'),

(2074,'MMLXXIV'),

(2152,'MMCLII'),

(2212,'MMCCXII'),

(2343,'MMCCCXLIII'),

(2499,'MMCDXCIX'),

(2574,'MMDLXXIV'),

(2646,'MMDCXLVI'),

(2723,'MMDCCXXIII'),

(2892,'MMDCCCXCII'),

(2975,'MMCMLXXV'),

(3051,'MMMLI'),

(3185,'MMMCLXXXV'),

(3250,'MMMCCL'),

(3313,'MMMCCCXIII'),

(3408,'MMMCDVIII'),

(3501,'MMMDI'),

(3610,'MMMDCX'),

(3743,'MMMDCCXLIII'),

(3844,'MMMDCCCXLIV'),

(3888,'MMMDCCCLXXXVIII'),

(3940,'MMMCMXL'),

(3999,'MMMCMXCIX'),

(4000,'MMMM'),

(4500,'MMMMD'),

(4888,'MMMMDCCCLXXXVIII'),

(4999,'MMMMCMXCIX'))

deftestToRomanKnownValues(self):

"""toRomanshouldgiveknownresultwithknowninput"""

forinteger,numeralinself.knownValues:

result=roman71.toRoman(integer)

self.assertEqual(numeral,result)

deftestFromRomanKnownValues(self):

"""fromRomanshouldgiveknownresultwithknowninput"""

forinteger,numeralinself.knownValues:

result=roman71.fromRoman(numeral)

self.assertEqual(integer,result)

classToRomanBadInput(unittest.TestCase):

deftestTooLarge(self):

"""toRomanshouldfailwithlargeinput"""

self.assertRaises(roman71.OutOfRangeError,roman71.toRoman,5000)

deftestZero(self):

"""toRomanshouldfailwith0input"""

self.assertRaises(roman71.OutOfRangeError,roman71.toRoman,0)

deftestNegative(self):

"""toRomanshouldfailwithnegativeinput"""

self.assertRaises(roman71.OutOfRangeError,roman71.toRoman,-1)

deftestNonInteger(self):

"""toRomanshouldfailwithnon-integerinput"""

self.assertRaises(roman71.NotIntegerError,roman71.toRoman,0.5)

classFromRomanBadInput(unittest.TestCase):

deftestTooManyRepeatedNumerals(self):

"""fromRomanshouldfailwithtoomanyrepeatednumerals"""

forsin('MMMMM','DD','CCCC','LL','XXXX','VV','IIII'

self.assertRaises(roman71.InvalidRomanNumeralError,roman71.fromRoman,s)

deftestRepeatedPairs(self):

"""fromRomanshouldfailwithrepeatedpairsofnumerals"""

forsin('CMCM','CDCD','XCXC','XLXL','IXIX','IVIV'):

self.assertRaises(roman71.InvalidRomanNumeralError,roman71.fromRoman,s)

deftestMalformedAntecedent(self):

"""fromRomanshouldfailwithmalformedantecedents"""

forsin('IIMXCC','VX','DCM','CMM','IXIV',

'MCMC','XCX','IVI','LM','LD','LC'):

self.assertRaises(roman71.InvalidRomanNumeralError,roman71.fromRoman,s)

deftestBlank(self):

"""fromRomanshouldfailwithblankstring"""

self.assertRaises(roman71.InvalidRomanNumeralError,roman71.fromRoman,

classSanityCheck(unittest.TestCase):

deftestSanity(self):

"""fromRoman(toRoman(n))==nforalln"""

forintegerinrange(1,5000):

numeral=roman71.toRoman(integer)

result=roman71.fromRoman(numeral)

self.assertEqual(integer,result)

classCaseCheck(unittest.TestCase):

deftestToRomanCase(self):

"""toRomanshouldalwaysreturnuppercase"""

forintegerinrange(1,5000):

numeral=roman71.toRoman(integer)

self.assertEqual(numeral,numeral.upper())

deftestFromRomanCase(self):

"""fromRomanshouldonlyacceptuppercaseinput"""

forintegerinrange(1,5000):

numeral=roman71.toRoman(integer)

roman71.fromRoman(numeral.upper())

self.assertRaises(roman71.InvalidRomanNumeralError,

roman71.fromRoman,numeral.lower())

if__name__=="__main__":

unittest.main()

4000 4000 4500 48884999“” 4000 toRoman 4000-4999 5000

“” 'MMMM' fromRoman MMMM“”'MMMMM'

1 3999 for 4999

15.7. romantest71.py roman71.py

fromRomanshouldonlyacceptuppercaseinput...ERROR

toRomanshouldalwaysreturnuppercase...ERROR

fromRomanshouldfailwithblankstring...ok

fromRomanshouldfailwithmalformedantecedents...ok

fromRomanshouldfailwithrepeatedpairsofnumerals...ok

fromRomanshouldfailwithtoomanyrepeatednumerals...ok

fromRomanshouldgiveknownresultwithknowninput...ERROR

toRomanshouldgiveknownresultwithknowninput...ERROR

fromRoman(toRoman(n))==nforalln...ERROR

toRomanshouldfailwithnon-integerinput...ok

toRomanshouldfailwithnegativeinput...ok

toRomanshouldfailwithlargeinput...ok

toRomanshouldfailwith0input...ok

1 4999 toRoman 1 3999 4000

fromRoman 'MMMM' fromRomantoRoman 4000 toRoman 4000 toRoman

======================================================================

ERROR:fromRomanshouldonlyacceptuppercaseinput

----------------------------------------------------------------------

Traceback(mostrecentcalllast):

File"C:\docbook\dip\py\roman\stage7\romantest71.py",line161,intestFromRomanCase

numeral=roman71.toRoman(integer)

File"roman71.py",line28,intoRoman

raiseOutOfRangeError,"numberoutofrange(mustbe1..3999)"

OutOfRangeError:numberoutofrange(mustbe1..3999)

======================================================================

ERROR:toRomanshouldalwaysreturnuppercase

----------------------------------------------------------------------

Traceback(mostrecentcalllast):

File"C:\docbook\dip\py\roman\stage7\romantest71.py",line155,intestToRomanCase

numeral=roman71.toRoman(integer)

File"roman71.py",line28,intoRoman

raiseOutOfRangeError,"numberoutofrange(mustbe1..3999)"

OutOfRangeError:numberoutofrange(mustbe1..3999)

======================================================================

ERROR:fromRomanshouldgiveknownresultwithknowninput

----------------------------------------------------------------------

Traceback(mostrecentcalllast):

File"C:\docbook\dip\py\roman\stage7\romantest71.py",line102,intestFromRomanKnownValues

result=roman71.fromRoman(numeral)

File"roman71.py",line47,infromRoman

raiseInvalidRomanNumeralError,'InvalidRomannumeral:%s'%s

InvalidRomanNumeralError:InvalidRomannumeral:MMMM

======================================================================

ERROR:toRomanshouldgiveknownresultwithknowninput

----------------------------------------------------------------------

Traceback(mostrecentcalllast):

File"C:\docbook\dip\py\roman\stage7\romantest71.py",line96,intestToRomanKnownValues

result=roman71.toRoman(integer)

File"roman71.py",line28,intoRoman

raiseOutOfRangeError,"numberoutofrange(mustbe1..3999)"

OutOfRangeError:numberoutofrange(mustbe1..3999)

======================================================================

ERROR:fromRoman(toRoman(n))==nforalln

----------------------------------------------------------------------

Traceback(mostrecentcalllast):

File"C:\docbook\dip\py\roman\stage7\romantest71.py",line147,intestSanity

numeral=roman71.toRoman(integer)

File"roman71.py",line28,intoRoman

raiseOutOfRangeError,"numberoutofrange(mustbe1..3999)"

OutOfRangeError:numberoutofrange(mustbe1..3999)

----------------------------------------------------------------------

Ran13testsin2.213s

FAILED(errors=5)

“ ”

15.8. roman72.py

py/roman/stage7/

"""ConverttoandfromRomannumerals"""

importre

#Defineexceptions

classRomanError(Exception):pass

classOutOfRangeError(RomanError):pass

classNotIntegerError(RomanError):pass

classInvalidRomanNumeralError(RomanError):pass

#Definedigitmapping

romanNumeralMap=(('M',1000),

('CM',900),

('D',500),

('CD',400),

('C',100),

('XC',90),

('L',50),

('XL',40),

('X',10),

('IX',9),

('V',5),

('IV',4),

('I',1))

deftoRoman(n):

"""convertintegertoRomannumeral"""

ifnot(0<n<5000):

raiseOutOfRangeError,"numberoutofrange(mustbe1..4999)"

ifint(n)<>n:

raiseNotIntegerError,"non-integerscannotbeconverted"

result=""

fornumeral,integerinromanNumeralMap:

whilen>=integer:

result+=numeral

n-=integer

returnresult

#DefinepatterntodetectvalidRomannumerals

romanNumeralPattern='^M?M?M?M?(CM|CD|D?C?C?C?)(XC|XL|L?X?X?X?)(IX|IV|V?I?I?I?)$'

deffromRoman(s):

"""convertRomannumeraltointeger"""

ifnots:

raiseInvalidRomanNumeralError,'Inputcannotbeblank'

ifnotre.search(romanNumeralPattern,s):

raiseInvalidRomanNumeralError,'InvalidRomannumeral:%s'

result=0

index=0

fornumeral,integerinromanNumeralMap:

whiles[index:index+len(numeral)]==numeral:

result+=integer

index+=len(numeral)

returnresult

toRoman 0<n<4000 0<n<5000 raise1..49991..39991000 'M' 4000 'MMMM' fromRoman romanNumeralPattern M4 M3 4999 3999 fromRoman 'MMMM'

15.9. romantest72.py roman72.py

fromRomanshouldonlyacceptuppercaseinput...ok

toRomanshouldalwaysreturnuppercase...ok

fromRomanshouldfailwithblankstring...ok

fromRomanshouldfailwithmalformedantecedents...ok

fromRomanshouldfailwithrepeatedpairsofnumerals...ok

fromRomanshouldfailwithtoomanyrepeatednumerals...ok

fromRomanshouldgiveknownresultwithknowninput...ok

toRomanshouldgiveknownresultwithknowninput...ok

fromRoman(toRoman(n))==nforalln...ok

toRomanshouldfailwithnon-integerinput...ok

toRomanshouldfailwithnegativeinput...ok

toRomanshouldfailwithlargeinput...ok

toRomanshouldfailwith0input...ok

----------------------------------------------------------------------

Ran13testsin3.685s

OK

“ ”

<< 12345 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

15.3.

“ ”“ ”“ ”“ ”“ ”

“ ”“ ” fromRoman

15.10.

>>>importre

>>>pattern='^M?M?M?$'

>>>re.search(pattern,'M')

<SRE_Matchobjectat01090490>

>>>compiledPattern=re.compile(pattern)

>>>compiledPattern

<SRE_Patternobjectat00F06E28>

>>>dir(compiledPattern)

['findall','match','scanner','search','split','sub','subn']

>>>compiledPattern.search('M')

<SRE_Matchobjectat01104928>

re.search pattern'M' match re.compilepattern 'M'

re.compilepattern re search sub

'M'pattern search 'M' re.searchre.searchpattern search

patternpattern

15.11.roman81.py

py/roman/stage8/

,

#toRomanandrestofmoduleomittedforclarity

romanNumeralPattern=\

re.compile('^M?M?M?M?(CM|CD|D?C?C?C?)(XC|XL|L?X?X?X?)(IX|IV|V?I?I?I?)$'

deffromRoman(s):

"""convertRomannumeraltointeger"""

ifnots:

raiseInvalidRomanNumeralError,'Inputcannotbeblank'

ifnotromanNumeralPattern.search(s):

raiseInvalidRomanNumeralError,'InvalidRomannumeral:%s'

result=0

index=0

fornumeral,integerinromanNumeralMap:

whiles[index:index+len(numeral)]==numeral:

result+=integer

index+=len(numeral)

returnresult

romanNumeralPattern re.compilepattern romanNumeralPattern re.searchimportromanNumeralPattern fromRoman

15.12. romantest81.py roman81.py

.............

----------------------------------------------------------------------

Ran13testsin3.385s

OK

-v docstring F E 13 3.385 3.685 8% search54%

comp.lang.python {m,n}

15.13.roman82.py

py/roman/stage8/

,

#restofprogramomittedforclarity

#oldversion

#romanNumeralPattern=\

#re.compile('^M?M?M?M?(CM|CD|D?C?C?C?)(XC|XL|L?X?X?X?)(IX|IV|V?I?I?I?)$')

#newversion

romanNumeralPattern=\

re.compile('^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$'

M?M?M?M? M{0,4}“ 04 M” C?C?C?C{0,3}“ 03 C” X I

15.14. romantest82.py roman82.py

.............

----------------------------------------------------------------------

Ran13testsin3.315s

OK

2% search search 11%)60% 10%.“ fromRoman”Bug

Bug 7.5“” , Python

15.15.roman83.py

py/roman/stage8/

,

#restofprogramomittedforclarity

#oldversion

#romanNumeralPattern=\

#re.compile('^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$')

#newversion

romanNumeralPattern=re.compile('''

^#beginningofstring

M{0,4}#thousands-0to4M's

(CM|CD|D?C{0,3})#hundreds-900(CM),400(CD),0-300(0to3C's),

#or500-800(D,followedby0to3C's)

(XC|XL|L?X{0,3})#tens-90(XC),40(XL),0-30(0to3X's),

#or50-80(L,followedby0to3X's)

(IX|IV|V?I{0,3})#ones-9(IX),4(IV),0-3(0to3I's),

#or5-8(V,followedby0to3I's)

$#endofstring

''',re.VERBOSE)

re.compile re.VERBOSE Pythonre.compile“ verbose”

15.16. romantest83.py roman83.py

.............

----------------------------------------------------------------------

Ran13testsin3.315s

OK

“ verbose”patternre.compile“ verbose”

<< 12345 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

15.4. 5000

15.17.roman9.py

py/roman/stage9/

,

#Defineexceptions

classRomanError(Exception):pass

classOutOfRangeError(RomanError):pass

classNotIntegerError(RomanError):pass

classInvalidRomanNumeralError(RomanError):pass

#Romannumeralsmustbelessthan5000

MAX_ROMAN_NUMERAL=4999

#Definedigitmapping

romanNumeralMap=(('M',1000),

('CM',900),

('D',500),

('CD',400),

('C',100),

('XC',90),

('L',50),

('XL',40),

('X',10),

('IX',9),

('V',5),

('IV',4),

('I',1))

#Createtablesforfastconversionofromannumerals.

#SeefillLookupTables()below.

toRomanTable=[None]#SkipanindexsinceRomannumeralshavenozero

fromRomanTable={}

deftoRoman(n):

"""convertintegertoRomannumeral"""

ifnot(0<n<=MAX_ROMAN_NUMERAL):

raiseOutOfRangeError,"numberoutofrange(mustbe1..%s)"

ifint(n)<>n:

raiseNotIntegerError,"non-integerscannotbeconverted"

returntoRomanTable[n]

deffromRoman(s):

"""convertRomannumeraltointeger"""

ifnots:

raiseInvalidRomanNumeralError,"Inputcannotbeblank"

ifnotfromRomanTable.has_key(s):

raiseInvalidRomanNumeralError,"InvalidRomannumeral:%s"

returnfromRomanTable[s]

deftoRomanDynamic(n):

"""convertintegertoRomannumeralusingdynamicprogramming"""

result=""

fornumeral,integerinromanNumeralMap:

ifn>=integer:

result=numeral

n-=integer

break

ifn>0:

result+=toRomanTable[n]

returnresult

deffillLookupTables():

"""computeallthepossibleromannumerals"""

#Savethevaluesintwoglobaltablestoconverttoandfromintegers.

forintegerinrange(1,MAX_ROMAN_NUMERAL+1):

romanNumber=toRomanDynamic(integer)

toRomanTable.append(romanNumber)

fromRomanTable[romanNumber]=integer

fillLookupTables()

15.18. romantest9.py roman9.py

.............

----------------------------------------------------------------------

Ran13testsin0.791s

OK

133.315

......

<< 12345 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

15.5.“”“”Bug

Python

Bug

Python

unittest.TestCase assertEqual assertRaises if__name__ unittest.main() verbose regular

XProgramming.com

<< 12345 FunctionalProgramming>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>FunctionalProgramming > <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

16.2. Python

sys.argv 9 XML

16.3.fullpath.py

,

importsys,os

print'sys.argv[0]=',sys.argv[0]

pathname=os.path.dirname(sys.argv[0])

print'path=',pathname

print'fullpath=',os.path.abspath(pathname)

sys.argv[0]os.path.dirname os.path.dirname

os.path.abspath

os.path.abspath

16.4.os.path.abspath

>>>importos

>>>os.getcwd()

/home/you

>>>os.path.abspath('')

/home/you

>>>os.path.abspath('.ssh')

/home/you/.ssh

>>>os.path.abspath('/home/you/.ssh')

/home/you/.ssh

>>>os.path.abspath('.ssh/../foo/')

/home/you/foo

os.getcwd() os.path.abspath os.getcwd()

os.path.abspath os.path.abspathos.path.abspath ‘foo’ os.path.abspath

os.path.abspath

os.path.abspath /usr/os.path.abspath('bin/../local/bin') /usr/local/bin

16.5.fullpath.py

[you@localhostpy]$python/home/you/diveintopython/common/py/fullpath.py

sys.argv[0]=/home/you/diveintopython/common/py/fullpath.py

path=/home/you/diveintopython/common/py

fullpath=/home/you/diveintopython/common/py

[you@localhostdiveintopython]$pythoncommon/py/fullpath.py

sys.argv[0]=common/py/fullpath.py

path=common/py

fullpath=/home/you/diveintopython/common/py

[you@localhostdiveintopython]$cdcommon/py

[you@localhostpy]$pythonfullpath.py

sys.argv[0]=fullpath.py

path=

fullpath=/home/you/diveintopython/common/py

sys.argv[0] os.path.dirname os.path.abspath

sys.argv[0] os.path.dirnameos.path.abspath

os.path.dirname os.path.abspath

os os.path os.path.abspathWindows MacOS os

. regression.py

16.6.

importsys,os,re,unittest

defregressionTest():

path=os.getcwd()

sys.path.append(path)

files=os.listdir(path)

path Python Python pathPython

regression.py regression.py

<<FunctionalProgramming 12345678 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>FunctionalProgramming > <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

16.3.

Python filter [7] filter filter filter

true

16.7. filter

>>>defodd(n):

...returnn%2

...

>>>li=[1,2,3,5,9,10,256,-3]

>>>filter(odd,li)

[1,3,5,9,-3]

>>>[eforeinliifodd(e)]

>>>filteredList=[]

>>>forninli:

...ifodd(n):

...filteredList.append(n)

...

>>>filteredList

[1,3,5,9,-3]

oddmod“ %” n True Falsefilter oddli odd odd Python 4.5“” for“ ” filter for“ ”

16.8.regression.py filter

files=os.listdir(path)

test=re.compile("test\.py$",re.IGNORECASE)

files=filter(test.search,files)

16.2“” path files 15.3“” search searchMatch None, Pythonnull files test search PythontrueMatch searchfalse None

. Python2.0 filter2.0 filter map map filter Python

16.9.

files=os.listdir(path)

test=re.compile("test\.py$",re.IGNORECASE)

files=[fforfinfilesiftest.search(f)]

filter

Footnotes

[7] filter __getitem__ filter

<< 12345678 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>FunctionalProgramming > <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

16.4. map filter

16.10. map

>>>defdouble(n):

...returnn*2

...

>>>li=[1,2,3,5,9,10,256,-3]

>>>map(double,li)

[2,4,6,10,18,20,512,-6]

>>>[double(n)forninli]

[2,4,6,10,18,20,512,-6]

>>>newlist=[]

>>>forninli:

...newlist.append(double(n))

...

>>>newlist

[2,4,6,10,18,20,512,-6]

map [8]2 Python2.0 map

VisualBasic for

16.11.map

>>>li=[5,'a',(2,'b')]

>>>map(double,li)

[10,'aa',(2,'b',2,'b')]

map double2 Python 2

16.12.regression.py map

filenameToModuleName=lambdaf:os.path.splitext(f)[0]

moduleNames=map(filenameToModuleName,files)

4.7“lambda” lambda 6.17“” os.path.splitext name,extension filenameToModuleName

mapfiles filenameToModuleNamemoduleNames

Footnotes

[8] map filter

<< 12345678 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>FunctionalProgramming > <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

16.5. for map filter

filter

filter for if map for forBug“ ”

Python

Python filter map for if Python VisualBasicBug

<< 12345678 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>FunctionalProgramming > <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

16.6.

importmodule

16.13.

importsys,os,re,unittest

sys os re unittest

16.14.

>>>sys=__import__('sys')

>>>os=__import__('os')

>>>re=__import__('re')

>>>unittest=__import__('unittest')

>>>sys

>>><module'sys'(built-in)>

>>>os

>>><module'os'from'/usr/local/lib/python2.2/os.pyc'>

__import__ import sys sys importsys osos

__import__

16.15.

>>>moduleNames=['sys','os','re','unittest']

>>>moduleNames

['sys','os','re','unittest']

>>>modules=map(__import__,moduleNames)

>>>modules

[<module'sys'(built-in)>,

<module'os'from'c:\Python22\lib\os.pyc'>,

<module're'from'c:\Python22\lib\re.pyc'>,

<module'unittest'from'c:\Python22\lib\unittest.pyc'>]

>>>modules[0].version

'2.2.2(#37,Nov262002,10:24:37)[MSC32bit(Intel)]'

>>>importsys

>>>sys.version

'2.2.2(#37,Nov262002,10:24:37)[MSC32bit(Intel)]'

moduleNames __import__ moduleNames __import__

Python modules[0]sys modules[0].versionsys.version import

<< 12345678 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>FunctionalProgramming > <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

16.7.

16.16.regressionTest

defregressionTest():

path=os.path.abspath(os.path.dirname(sys.argv[0]))

files=os.listdir(path)

test=re.compile("test\.py$",re.IGNORECASE)

files=filter(test.search,files)

filenameToModuleName=lambdaf:os.path.splitext(f)[0]

moduleNames=map(filenameToModuleName,files)

modules=map(__import__,moduleNames)

load=unittest.defaultTestLoader.loadTestsFromModule

returnunittest.TestSuite(map(load,modules))

c:\diveintopython\py 16.2“” path

16.17.1:

>>>importsys,os,re,unittest

>>>path=r'c:\diveintopython\py'

>>>files=os.listdir(path)

>>>files

['BaseHTMLProcessor.py','LICENSE.txt','apihelper.py','apihelpertest.py',

'argecho.py','autosize.py','builddialectexamples.py','dialect.py',

'fileinfo.py','fullpath.py','kgptest.py','makerealworddoc.py',

'odbchelper.py','odbchelpertest.py','parsephone.py','piglatin.py',

'plural.py','pluraltest.py','pyfontify.py','regression.py','roman.py','romantest.py',

'uncurly.py','unicode2koi8r.py','urllister.py','kgp','plural','roman',

'colorize.py']

files .pyc

16.18.2:

>>>test=re.compile("test\.py$",re.IGNORECASE)

>>>files=filter(test.search,files)

>>>files

['apihelpertest.py','kgptest.py','odbchelpertest.py','pluraltest.py','romantest.py']

test.py“ ”

SOMETHINGtest.py

16.19.3:

>>>filenameToModuleName=lambdaf:os.path.splitext(f)[0]

>>>filenameToModuleName('romantest.py')

'romantest'

>>>filenameToModuleName('odchelpertest.py')

'odbchelpertest'

>>>moduleNames=map(filenameToModuleName,files)

>>>moduleNames

['apihelpertest','kgptest','odbchelpertest','pluraltest','romantest']

4.7“lambda” lambda os.path.splitextfilenameToModuleName lambda deffilenameToModuleName

map

16.20.4:

>>>modules=map(__import__,moduleNames)

>>>modules

[<module'apihelpertest'from'apihelpertest.py'>,

<module'kgptest'from'kgptest.py'>,

<module'odbchelpertest'from'odbchelpertest.py'>,

<module'pluraltest'from'pluraltest.py'>,

<module'romantest'from'romantest.py'>]

>>>modules[-1]

<module'romantest'from'romantest.py'>

16.6“” map __import__

modules romantest importromantest

16.21.5:

>>>load=unittest.defaultTestLoader.loadTestsFromModule

>>>map(load,modules)

[<unittest.TestSuitetests=[

<unittest.TestSuitetests=[<apihelpertest.BadInputtestMethod=testNoObject>]>,

<unittest.TestSuitetests=[<apihelpertest.KnownValuestestMethod=testApiHelper>]>,

<unittest.TestSuitetests=[

<apihelpertest.ParamCheckstestMethod=testCollapse>,

<apihelpertest.ParamCheckstestMethod=testSpacing>]>,

...

]

]

>>>unittest.TestSuite(map(load,modules))

loadTestsFromModuleunittest.TestSuite TestSuite TestSuite TestSuite unittest

unittest unittest.main() unittest.main()unittest.TestProgram unittest.defaultTestLoader __import__('__main__') unittest

16.22.6: unittest

if__name__=="__main__":

unittest.main(defaultTest="regressionTest")

unittest unittest.defaultTestLoaderregressionTest unittest TestSuiteregressionTest

<< 12345678 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>FunctionalProgramming > <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

16.8.regression.py

filter map

<< 12345678 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>>plural.py,1 <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

17.2.plural.py,1

17.1.plural1.py

importre

defplural(noun):

ifre.search('[sxz]$',noun):

returnre.sub('$','es',noun)

elifre.search('[^aeioudgkprt]h$',noun):

returnre.sub('$','es',noun)

elifre.search('[^aeiou]y$',noun):

returnre.sub('y$','ies',noun)

else:

returnnoun+'s'

7 “ ” [sxz]“ s x z” $ noun sx zre.sub

17.2. re.sub

>>>importre

>>>re.search('[abc]','Mark')

<_sre.SRE_Matchobjectat0x001C1FA8>

>>>re.sub('[abc]','o','Mark')

'Mork'

>>>re.sub('[abc]','o','rock')

'rook'

>>>re.sub('[abc]','o','caps')

'oops'

Mark a b c a

a b c o Mark Mork rock rook

caps oaps re.sub caps oops ca o

17.3. plural1.py

importre

defplural(noun):

ifre.search('[sxz]$',noun):

returnre.sub('$','es',noun)

elifre.search('[^aeioudgkprt]h$',noun):

returnre.sub('$','es',noun)

elifre.search('[^aeiou]y$',noun):

returnre.sub('y$','ies',noun)

else:

returnnoun+'s'

plural es es noun+

'es' ^ [^abc]“ a b

[^aeioudgkprt] a e i o u d g k p r thHY a e i o uYIY

17.4.

>>>importre

>>>re.search('[^aeiou]y$','vacancy')

<_sre.SRE_Matchobjectat0x001C1FA8>

>>>re.search('[^aeiou]y$','boy')

>>>

>>>re.search('[^aeiou]y$','day')

>>>

>>>re.search('[^aeiou]y$','pita')

>>>

vacancy cy c a e i ouboy oy y o day ay

pita y

17.5. re.sub

>>>re.sub('y$','ies','vacancy')

'vacancies'

>>>re.sub('y$','ies','agency')

'agencies'

>>>re.sub('([^aeiou])y$',r'\1ies','vacancy')

'vacancies'

vacancy vacancies agency agencies boy

boies re.search re.sub

7.6“:” rememberedgroup y \1“ ” y c c

c ies y \2 \3

\1“ SXZES ”“ SXZES ”

<< 12345678 plural.py,2>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>>plural.py,2 <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

17.3.plural.py,2

17.6.plural2.py

importre

defmatch_sxz(noun):

returnre.search('[sxz]$',noun)

defapply_sxz(noun):

returnre.sub('$','es',noun)

defmatch_h(noun):

returnre.search('[^aeioudgkprt]h$',noun)

defapply_h(noun):

returnre.sub('$','es',noun)

defmatch_y(noun):

returnre.search('[^aeiou]y$',noun)

defapply_y(noun):

returnre.sub('y$','ies',noun)

defmatch_default(noun):

return1

defapply_default(noun):

returnnoun+'s'

rules=((match_sxz,apply_sxz),

(match_h,apply_h),

(match_y,apply_y),

(match_default,apply_default)

)

defplural(noun):

formatchesRule,applyRuleinrules:

ifmatchesRule(noun):

returnapplyRule(noun)

rules for rules for matchesRulematch_sxz applyRule apply_sxz matchesRulematch_h applyRule apply_h

Python rules for matchesRuleapplyRule for matches_sxz(noun)

for apply_sxz(noun)

for

17.7. plural

defplural(noun):

ifmatch_sxz(noun):

returnapply_sxz(noun)

ifmatch_h(noun):/

returnapply_h(noun)

ifmatch_y(noun):

returnapply_y(noun)

ifmatch_default(noun):

returnapply_default(noun)

plural plural

... plural if match_fooapply_foo rules

<<plural.py,1 12345678 plural.py,3>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>>plural.py,3 <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

17.4.plural.py,3

rules

17.8.plural3.py

importre

rules=\

(

(

lambdaword:re.search('[sxz]$',word),

lambdaword:re.sub('$','es',word)

),

(

lambdaword:re.search('[^aeioudgkprt]h$',word),

lambdaword:re.sub('$','es',word)

),

(

lambdaword:re.search('[^aeiou]y$',word),

lambdaword:re.sub('y$','ies',word)

),

(

lambdaword:re.search('$',word),

lambdaword:re.sub('$','s',word)

)

)

defplural(noun):

formatchesRule,applyRuleinrules:

ifmatchesRule(noun):

returnapplyRule(noun)

2 match_sxz apply_sxz lambda“ ”rules. plurallambda plural

rules re.search re.sub

<<plural.py,2 12345678 plural.py,4>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>>plural.py,4 <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

17.5.plural.py,4

17.9.plural4.py

importre

defbuildMatchAndApplyFunctions((pattern,search,replace)):

matchFunction=lambdaword:re.search(pattern,word)

applyFunction=lambdaword:re.sub(search,replace,word)

return(matchFunction,applyFunction)

buildMatchAndApplyFunctions pattern searchreplace lambdawordbuildMatchAndApplyFunctions pattern word re.search

buildMatchAndApplyFunctions search replace word

re.sub closures word search replace

buildMatchAndApplyFunctions matchFunctionpattern applyFunction search replacebuildMatchAndApplyFunctions

17.10.plural4.py

patterns=\

(

('[sxz]$','$','es'),

('[^aeioudgkprt]h$','$','es'),

('(qu|[^aeiou])y$','y$','ies'),

('$','$','s')

)

rules=map(buildMatchAndApplyFunctions,patterns)

re.search re.sub patterns buildMatchAndApplyFunctions rules re.search

rules rules

17.11.

rules=\

(

(

lambdaword:re.search('[sxz]$',word),

lambdaword:re.sub('$','es',word)

),

(

lambdaword:re.search('[^aeioudgkprt]h$',word),

lambdaword:re.sub('$','es',word)

),

(

lambdaword:re.search('[^aeiou]y$',word),

lambdaword:re.sub('y$','ies',word)

),

(

lambdaword:re.search('$',word),

lambdaword:re.sub('$','s',word)

)

)

17.12.plural4.py

defplural(noun):

formatchesRule,applyRuleinrules:

ifmatchesRule(noun):

returnapplyRule(noun)

rules plural 2 3 lambda4 buildMatchAndApplyFunctions plural

buildMatchAndApplyFunctions

17.13. buildMatchAndApplyFunctions

defbuildMatchAndApplyFunctions((pattern,search,replace)):

pattern search replace

17.14.

>>>deffoo((a,b,c)):

...printc

...printb

...printa

>>>parameters=('apple','bear','catnap')

>>>foo(parameters)

catnap

bear

apple

foo foo

patterns map(buildMatchAndApplyFunctions,

patterns) buildMatchAndApplyFunctions mappatterns buildMatchAndApplyFunctionsbuildMatchAndApplyFunctions

<<plural.py,3 12345678 plural.py,5>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>>plural.py,5 <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

17.6.plural.py,5

rules.en“ en”

17.15.rules.en

[sxz]$$es

[^aeioudgkprt]h$$es

[^aeiou]y$y$ies

$$s

17.16.plural5.py

importre

importstring

defbuildRule((pattern,search,replace)):

returnlambdaword:re.search(pattern,word)andre.sub(search,replace,word)

defplural(noun,language='en'):

lines=file('rules.%s'%language).readlines()

patterns=map(string.split,lines)

rules=map(buildRule,patterns)

forruleinrules:

result=rule(noun)

ifresult:returnresult

plural en language

language language en rules.en string.split [sxz]$$es ('[sxz]$','$','es') patterns 4 patterns rules buildRulebuildRule(('[sxz]$','$','es')) wordre.search('[sxz]$',word)re.sub('$','es',word)

None

plural language

plural“ ”

<<plural.py,4 12345678 plural.py,6>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>>plural.py,6 <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

17.7.plural.py,6

Generator

17.17.plural6.py

importre

defrules(language):

forlineinfile('rules.%s'%language):

pattern,search,replace=line.split()

yieldlambdaword:re.search(pattern,word)andre.sub(search,replace,word)

defplural(noun,language='en'):

forapplyRuleinrules(language):

result=applyRule(noun)

ifresult:returnresult

17.18.

>>>defmake_counter(x):

...print'enteringmake_counter'

...while1:

...yieldx

...print'incrementingx'

...x=x+1

...

>>>counter=make_counter(2)

>>>counter

<generatorobjectat0x001C9C10>

>>>counter.next()

enteringmake_counter

2

>>>counter.next()

incrementingx

3

>>>counter.next()

incrementingx

4

make_counter yield x make_counter make_counter print

make_counter next() make_counter yield(yield) 2

make_counter(2) next() yield print incrementingx x=x+

1 while yieldx x3 counter.next() x 4 make_counter x

17.19.

deffibonacci(max):

a,b=0,1

whilea<max:

yielda

a,b=b,a+b

Fibonaccisequence 0 1 a 0 b 1

ab aa+b b a 3 b 5 a,b=b,a+b a

5 b) b 8 a b

Fibonacci for

17.20.for

>>>forninfibonacci(1000):

...printn,

01123581321345589144233377610987

for fibonacci for next() forn for n fibonacci yield fibonaccia max 1000 for

plural

17.21.

defrules(language):

forlineinfile('rules.%s'%language):

pattern,search,replace=line.split()

yieldlambdaword:re.search(pattern,word)andre.sub(search,replace,word)

defplural(noun,language='en'):

forapplyRuleinrules(language):

result=applyRule(noun)

ifresult:returnresult

forlineinfile(...) file next()

line.split()3 lambda pattern search replace

rules rules for for rules forrules forlineinfile(...)

5 5

PEP255PythonCookbook .

<<plural.py,5 12345678 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

17.8.

lambda

<<plural.py,6 12345678 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>>timeit <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

18.2. timeit

Python

“ ”

Python?

Python“ Python ” Python2.3 timeit

18.2. timeit

,

>>>importtimeit

>>>t=timeit.Timer("soundex.soundex('Pilgrim')",

..."importsoundex")

>>>t.timeit()

8.21683733547

>>>t.repeat(3,2000000)

[16.48319309109,16.46128984923,16.44203948912]

timeit Timer 'Pilgrim'Soundex Timer

timeit

Timer timeit()

Timer repeat() 3 1000000 repeat()

timeit Pythonhttp://docs.python.org/lib/node396.html

repeat() Python“ ”

Python Python

Python min

>>>min(t.repeat(3,1000000))

8.22203948912

timeit Python hotshot

<< 1234567 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

18.3.Soundex

“ ”

soundex/stage1/soundex1a.py source

allChars=string.uppercase+string.lowercase

ifnotre.search('^[%s]+$'%allChars,source):

return"0000"

soundex1a.py __main__ timeit

if__name__=='__main__':

fromtimeitimportTimer

names=('Woo','Pilgrim','Flingjingwaller')

fornameinnames:

statement="soundex('%s')"%name

t=Timer(statement,"from__main__importsoundex")

printname.ljust(15),soundex(name),min(t.repeat())

soundex1a.py

C:\samples\soundex\stage1>pythonsoundex1a.py

WooW00019.3356647283

PilgrimP42624.0772053431

FlingjingwallerF45235.0463220884

Woo Pilgrim Flingjingwaller

A-Z a-z soundex/stage1/soundex1b.py:

ifnotre.search('^[A-Za-z]+$',source):

return"0000"

timeit soundex1b.py soundex1a.py

C:\samples\soundex\stage1>pythonsoundex1b.py

WooW00017.1361133887

PilgrimP42621.8201693232

FlingjingwallerF45232.7262294509

15.3“” soundex/stage1/soundex1c.py

isOnlyChars=re.compile('^[A-Za-z]+$').search

defsoundex(source):

ifnotisOnlyChars(source):

return"0000"

soundex1c.py

C:\samples\soundex\stage1>pythonsoundex1c.py

WooW00014.5348347346

PilgrimP42619.2784703084

FlingjingwallerF45230.0893873383

source

soundex/stage1/soundex1d.py

ifnotsource:

return"0000"

forcinsource:

ifnot('A'<=c<='Z')andnot('a'<=c<='z'):

return"0000"

soundex1d.py

C:\samples\soundex\stage1>pythonsoundex1d.py

WooW00015.4065058548

PilgrimP42622.2753567842

FlingjingwallerF45237.5845122774

soundex1d.py PythonC Python Python......

Python isalpha()

soundex/stage1/soundex1e.py

if(notsource)and(notsource.isalpha()):

return"0000"

soundex1e.py?

C:\samples\soundex\stage1>pythonsoundex1e.py

WooW00013.5069504644

PilgrimP42618.2199394057

FlingjingwallerF45228.9975225902

18.3. soundex/stage1/soundex1e.py

importstring,re

charToSoundex={"A":"9",

"B":"1",

"C":"2",

"D":"3",

"E":"9",

"F":"1",

"G":"2",

"H":"9",

"I":"9",

"J":"2",

"K":"2",

"L":"4",

"M":"5",

"N":"5",

"O":"9",

"P":"1",

"Q":"2",

"R":"6",

"S":"2",

"T":"3",

"U":"9",

"V":"1",

"W":"9",

"X":"2",

"Y":"9",

"Z":"2"}

defsoundex(source):

if(notsource)and(notsource.isalpha()):

return"0000"

source=source[0].upper()+source[1:]

digits=source[0]

forsinsource[1:]:

s=s.upper()

digits+=charToSoundex[s]

digits2=digits[0]

fordindigits[1:]:

ifdigits2[-1]!=d:

digits2+=d

digits3=re.sub('9','',digits2)

whilelen(digits3)<4:

digits3+="0"

returndigits3[:4]

if__name__=='__main__':

fromtimeitimportTimer

names=('Woo','Pilgrim','Flingjingwaller')

fornameinnames:

statement="soundex('%s')"%name

t=Timer(statement,"from__main__importsoundex")

printname.ljust(15),soundex(name),min(t.repeat())

<<timeit 1234567 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

18.4.Soundex

soundex/stage1/soundex1c.py

charToSoundex={"A":"9",

"B":"1",

"C":"2",

"D":"3",

"E":"9",

"F":"1",

"G":"2",

"H":"9",

"I":"9",

"J":"2",

"K":"2",

"L":"4",

"M":"5",

"N":"5",

"O":"9",

"P":"1",

"Q":"2",

"R":"6",

"S":"2",

"T":"3",

"U":"9",

"V":"1",

"W":"9",

"X":"2",

"Y":"9",

"Z":"2"}

defsoundex(source):

#...inputcheckomittedforbrevity...

source=source[0].upper()+source[1:]

digits=source[0]

forsinsource[1:]:

s=s.upper()

digits+=charToSoundex[s]

soundex1c.py

C:\samples\soundex\stage1>pythonsoundex1c.py

WooW00014.5341678901

PilgrimP42619.2650071448

FlingjingwallerF45230.1003563302

upper() upper()

digits Python

Python join()

soundex/stage2/soundex2a.py map lambda

defsoundex(source):

#...

source=source.upper()

digits=source[0]+"".join(map(lambdac:charToSoundex[c],source[1:]))

soundex2a.py

C:\samples\soundex\stage2>pythonsoundex2a.py

WooW00015.0097526362

PilgrimP42619.254806407

FlingjingwallerF45229.3790847719

lambda

soundex/stage2/soundex2b.py map lambda

source=source.upper()

digits=source[0]+"".join([charToSoundex[c]forcinsource[1:]])

soundex2b.py soundex2a.py map lambda soundex1c.py

C:\samples\soundex\stage2>pythonsoundex2b.py

WooW00013.4221324219

PilgrimP42616.4901234654

FlingjingwallerF45225.8186157738

Python string.maketrans

soundex/stage2/soundex2c.py

allChar=string.uppercase+string.lowercase

charToSoundex=string.maketrans(allChar,"91239129922455912623919292"

defsoundex(source):

#...

digits=source[0].upper()+source[1:].translate(charToSoundex)

string.maketrans

ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz9123912992245591262391929291239129922455912623919292A9B1C2

timeit soundex2c.py

C:\samples\soundex\stage2>pythonsoundex2c.py

WooW00011.437645008

PilgrimP42613.2825062962

FlingjingwallerF45218.5570110168

Python

18.4. soundex/stage2/soundex2c.py

importstring,re

allChar=string.uppercase+string.lowercase

charToSoundex=string.maketrans(allChar,"91239129922455912623919292"

isOnlyChars=re.compile('^[A-Za-z]+$').search

defsoundex(source):

ifnotisOnlyChars(source):

return"0000"

digits=source[0].upper()+source[1:].translate(charToSoundex)

digits2=digits[0]

fordindigits[1:]:

ifdigits2[-1]!=d:

digits2+=d

digits3=re.sub('9','',digits2)

whilelen(digits3)<4:

digits3+="0"

returndigits3[:4]

if__name__=='__main__':

fromtimeitimportTimer

names=('Woo','Pilgrim','Flingjingwaller')

fornameinnames:

statement="soundex('%s')"%name

t=Timer(statement,"from__main__importsoundex")

printname.ljust(15),soundex(name),min(t.repeat())

<< 1234567 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

18.5.Soundex

soundex/stage2/soundex2c.py

digits2=digits[0]

fordindigits[1:]:

ifdigits2[-1]!=d:

digits2+=d

soundex2c.py

C:\samples\soundex\stage2>pythonsoundex2c.py

WooW00012.6070768771

PilgrimP42614.4033353401

FlingjingwallerF45219.7774882003

digits[-1]

soundex/stage3/soundex3a.py

digits2=''

last_digit=''

fordindigits:

ifd!=last_digit:

digits2+=d

last_digit=d

soundex3a.py soundex2c.py

C:\samples\soundex\stage3>pythonsoundex3a.py

WooW00011.5346048171

PilgrimP42613.3950636184

FlingjingwallerF45218.6108927252

soundex3a.py Python digits2[-1]

range() join()

soundex/stage3/soundex3b.py

digits2="".join([digits[i]foriinrange(len(digits))

ifi==0ordigits[i-1]!=digits[i]])

C:\samples\soundex\stage3>pythonsoundex3b.py

WooW00014.2245271396

PilgrimP42617.8337165757

FlingjingwallerF45225.9954005327

“ ” Python list('abc') ['a','b','c']

soundex/stage3/soundex3c.py

digits=list(source[0].upper()+source[1:].translate(charToSoundex))

i=0

foritemindigits:

ifitem==digits[i]:continue

i+=1

digits[i]=item

deldigits[i+1:]

digits2="".join(digits)

soundex3a.py soundex3b.py

C:\samples\soundex\stage3>pythonsoundex3c.py

WooW00014.1662554878

PilgrimP42616.0397885765

FlingjingwallerF45222.1789341942

“ clever” soundex2c.py

18.5. soundex/stage2/soundex2c.py

importstring,re

allChar=string.uppercase+string.lowercase

charToSoundex=string.maketrans(allChar,"91239129922455912623919292"

isOnlyChars=re.compile('^[A-Za-z]+$').search

defsoundex(source):

ifnotisOnlyChars(source):

return"0000"

digits=source[0].upper()+source[1:].translate(charToSoundex)

digits2=digits[0]

fordindigits[1:]:

ifdigits2[-1]!=d:

digits2+=d

digits3=re.sub('9','',digits2)

whilelen(digits3)<4:

digits3+="0"

returndigits3[:4]

if__name__=='__main__':

fromtimeitimportTimer

names=('Woo','Pilgrim','Flingjingwaller')

fornameinnames:

statement="soundex('%s')"%name

t=Timer(statement,"from__main__importsoundex")

printname.ljust(15),soundex(name),min(t.repeat())

<< 1234567 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

18.6.Soundex

soundex/stage2/soundex2c.py

digits3=re.sub('9','',digits2)

whilelen(digits3)<4:

digits3+="0"

returndigits3[:4]

soundex2c.py

C:\samples\soundex\stage2>pythonsoundex2c.py

WooW00012.6070768771

PilgrimP42614.4033353401

FlingjingwallerF45219.7774882003

soundex/stage4/soundex4a.py

digits3=''

fordindigits2:

ifd!='9':

digits3+=d

soundex4a.py

C:\samples\soundex\stage4>pythonsoundex4a.py

WooW0006.62865531792

PilgrimP4269.02247576158

FlingjingwallerF45213.6328416042

digits3=digits2.replace('9','')

soundex4b.py

C:\samples\soundex\stage4>pythonsoundex4b.py

WooW0006.75477414029

PilgrimP4267.56652144337

FlingjingwallerF45210.8727729362

soundex4b.py soundex4a.py

digits3+='000'

returndigits3[:4]

while source

while soundex4c.py

C:\samples\soundex\stage4>pythonsoundex4c.py

WooW0004.89129791636

PilgrimP4267.30642134685

FlingjingwallerF45210.689832367

soundex/stage4/soundex4d.py

return(digits2.replace('9','')+'000')[:4]

soundex4d.py soundex4c.py

C:\samples\soundex\stage4>pythonsoundex4d.py

WooW0004.93624105857

PilgrimP4267.19747593619

FlingjingwallerF45210.5490700634

<< 1234567 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

18.7. Python

C Python PythonC string.maketrans isalpha() Python

20/ Python

<< 1234567 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

PythonCookbook keydictionaryPythonLibraryReference dictionary

3.2.5.list

HowtoThinkLikeaComputerScientistlist, listPythonTutorial listPythonKnowledgeBase list listPythonLibraryReference list

3.3.Tuple

HowtoThinkLikeaComputerScientisttuple tuplePythonKnowledgeBase tuplePythonTutorial tuple

3.4.2.

PythonReferenceManualHowtoThinkLikeaComputerScientist

3.5.

PythonLibraryReferenceEffectiveAWKProgramming , ,0

3.6.list

PythonTutoriallist mapPythonTutorial listlist

3.7.list

PythonKnowledgeBase ,

PythonLibraryReferencePythonLibraryReference stringTheWholePythonFAQ joinlist

4

4.2.

PythonTutorial list

4.3.3.

PythonLibraryReference

4.5.

PythonTutorial

4.6.1.and-or

PythonCookbook and-or

4.7.1.lambda

PythonKnowledgeBase lambdaPythonTutorial lambdaPEP227 PythonTheWholePythonFAQ lambda

5

5.2.frommoduleimport

eff-bot importmodulevs.frommoduleimportPythonTutorial frommoduleimport*

5.3.2.self__init__

LearningtoProgramHowtoThinkLikeaComputerScientistPythonTutorialPythonKnowledgeBase

5.4.1.

PythonLibraryReference __class__PythonLibraryReference gc Python

5.5.UserDict:

PythonLibraryReference UserDict copy

5.7.

PythonReferenceManual

5.9.

PythonTutorial

6

6.1.1.

PythonTutorial ,PythonLibraryReferencePythonLibraryReference getpassPythonLibraryReference traceback,PythonReferenceManual try...except

6.2.4.

PythonTutorial listeff-bot PythonKnowledgeBasePythonLibraryReference

6.4.sys.modules

PythonTutorialPythonLibraryReference sys

6.5.Directory

PythonKnowledgeBase osPythonLibraryReference os os.path

7

7.6.:

RegularExpressionHOWTOPythonPythonLibraryReferenceremodule.

8HTML

8.4.BaseHTMLProcessor.py

W3CPythonLibraryReference htmlentitydefs

8.9.

web

: >DiveIntoPython> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

B.1Python

1.1.Python

Python,

1.2.WindowsPython

Windows, Python

1.3.MacOSXPython

MacOSX, Python:

1.4.MacOS9Python

MacOS9 Python,,

1.5.RedHatLinuxPython

http://www.python.org/ftp/python/, rpms/ PythonRPM rpm,:

1.6.DebianGNU/LinuxPython

Debian GNU/Linux, Python apt

1.7.Python

, http://www.python.org/ftp/python/ Python, .tgz, configure,make,makeinstall

1.8.PythonShell

Python,shell

1.9.

Python

2Python

2.1.

, Python

2.2.

Python, C++ Pascalinterface/implementation,:

2.3.

docstring() Python

2.4.

Python,

2.5.

Python begin end,, (

2.6.

Python

3

3.1.Dictionary

Dictionary Python,

3.2.List

List Pythonlist VisualBasic Powerbuilder, Pythonlist

3.3.Tuple

Tuplelisttuple

3.4.

Python,,

3.5.

Python, %s

3.6.list

Pythonlist,,list,listlist

3.7.list

key=valuekey-valuelist,list, join

3.8.

odbchelper.py

4

4.1.

Python 2 Python

4.2.

Python SQLServerTransact/SQL

4.3.typestrdir

Python VisualBasic

4.4.getattr

Python getattr

4.5.

Python3.6“list”

4.6.andor

Python and or

4.7.lambda

Python lambda Lisp

4.8.

4.9.

apihelper.py

5

5.1.

Python docstrings

5.2.frommoduleimport

Python importmodule2.4“”

5.3.

Python

5.4.

Python __init__

5.5.UserDict:

FileInfo UserDict UserDict FileInfo Python .py Python

5.6.

Python Python

5.7.

__getitem__ __setitem__ Python

5.8.

Python

5.9.

Python

5.10.

12 , getattrWeb

6

6.1.

Python try...except

6.2.

Python open open

6.3.for

Python for Python

6.4.sys.modules

Python,dictionary sys.modules

6.5.Directory

os.path,

6.6.

6.7.

5 fileinfo.py

7

7.1.

if splitjoin

7.2.

7.3.

“ MCMXLVI”“ 1946”(“ MDCCCLXXXVIII”“1888”)

7.4.{n,m}

,

7.5.

“ ”inlinedocumentation

7.6.:

7.7.

8HTML

8.1.

comp.lang.python: “ HTML[||]|munge] HTML ”“ HTML[||] ”

8.2.sgmllib.py

HTML: HTMLHTML sgmllib.pyPython

8.3.HTML

HTML SGMLParser

8.4.BaseHTMLProcessor.py

SGMLParser SGMLParser HTML(consumer): HTML SGMLParser SGMLParser(producer)

8.5.localsglobals

HTML, Python Python, locals globals,dictionary

8.6.dictionary

dictionarytuple

8.7.

comp.lang.python“ HTML ”[4](

HTML HTML HTML) HTMLBaseHTMLProcessor

8.8.dialect.py

Dialectizer BaseHTMLProcessor() <pre>...</pre>

8.9.

8.10.

Python sgmllib.py HTML

9XML

9.1.

XML SAX“ SimpleAPIforXML” XML 8 HTML sgmllib DOM“ DocumentObjectModel” XML Python Python DOM

9.2.

XML

9.3.XML

XML

9.4.Unicode

Unicode Python XMLunicode

9.5.

XML XML getElementsByTagName

9.6.

XML XML

9.7.Segue

OKthat'sitforthehard-coreXMLstuff. getattr

10ScriptsStreams

10.1.

Python (file-like)

10.2.

UNIX

10.3.

kgp.py XML

10.4.

XML ref p p refp p p

10.5.Creatingseparatehandlersbynodetype

XML XML Python Document Document

Elementforactual XMLtags Element Textforbitsoftext Commentforembeddedcomments Python

10.6.

Python XML

10.7.

10.8.

Python XML minidom XML Python Python“”

11HTTPWeb

11.1.

web URLXML , HTML XMLHTTPweb

11.2.HTTP

HTTP,Atomfeed;,,,

11.3.HTTP

HTTP

11.4.HTTPweb

, PythonHTTP ,

11.5.User-Agent

HTTPweb User-Agent, urllib urllib2

11.6.Last-ModifiedETag

webHTTP, Last-Modified ETag

11.7.

URL

11.8.

HTTP web,60%XML

11.9.

HTTPweb

11.10.

openanything.py

12SOAPWeb

12.1.

Google,? Google?

12.2.SOAP

, Python

12.3.SOAP

SOAP SOAP

12.4.SOAP

SOAP

12.5.WSDL

SOAPProxy SOAP SOAPProxy

12.6.WSDLSOAP

WSDL WSDL

12.7.Google

12.8.SOAP

SOAP

12.9.

SOAP

13

13.1.II

“ ”" Python

13.2.

(testsuite)

13.3.romantest.py

roman.py(testsuite)

13.4.Testingforsuccess

testcase

13.5.Testingforfailure

13.6.Testingforsanity

ABBA“ ”ABA

14

14.1.roman.py,1

roman.py

14.2.roman.py,2

roman

14.3.roman.py,3

toRoman1 3999

14.4.roman.py,4

toRoman fromRoman toRoman

14.5.roman.py,5

fromRoman toRoman

15

15.1.bugs

bug“ bug”Bug

15.2.

15.3.

15.4.

5000

15.5.

“”“”Bug

16FunctionalProgramming

16.1.

13 14 Python 15 Python

16.2.

Python

16.3.

16.4.

map filter

16.5.

for map filter

16.6.

16.7.

16.8.

regression.py

17

17.1.

Generator Python2.3

17.2.plural.py,1

17.3.plural.py,2

17.4.plural.py,3

rules

17.5.plural.py,4

17.6.plural.py,5

17.7.plural.py,6

Generator

17.8.

18

18.1.

18.2.timeit

Python

18.3.

Soundex

18.4.

Soundex

18.5.

Soundex

18.6.

Soundex

18.7.

Python

<< >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

C.1Python

2Python

2.1.

Windows ActivePythonIDE, File->Run...(Ctrl-R) Python

MacOS PythonIDE, Python->Runwindow...(Cmd-R) Python, IDE .py,,, Runas__main__ ,

UNIX( MacOSX), python

odbchelper.py

2.2.

VisualBasic,() function,()sub Python,( None), def

Java,C++, Python, Python

2.3.

, Perl qq/.../

PythonIDE docstring,, docstring, docstring

2.4.

Python import Perl require import

Python, module.function require Perl, module::function

2.5.

Python, C++ Java,

2.6.

C, Python ==, = C, Python,

MacPython, if__name__ ,,__main__

3

3.1.Dictionary

Pythondictionary Perlhash() Perl,% Python,, Python

Pythondictionary Java Hashtable

Pythondictionary VisualBasicScripting.Dictionary

3.1.2.Dictionary

Dictionary“ ”,,,(key)dictionary,dictionary

3.2.List

Pythonlist Perl Perl, @ Python,, Python

Pythonlist Java(, PythonlistJava) ArrayList,,

3.2.3.list

2.2.1, Python, Python( if),:

0false;true( "")false;truelist( [])false;listtruetuple( ())false;tupletruedictionary( {})false;dictionarytrue

Python2.2.1,, True FalsePython

3.3.Tuple

Tuplelist, tuplelist,tupletuplelist, tuplelist, listtuple

3.4.

(“ \”),, Python PythonIDE,,

3.5.

Python, C sprintf

3.7.list

joinlist;list

anystring.split(delimiter,1),,(list)(list),

4

4.2.

4.3.3.

Python Pythonman Python

4.7.lambda

lambda

4.8.

SQL ISNULL =NULLnull Python ==None isNone isNone

5

5.2.frommoduleimport

Python frommoduleimport* Perl usemodule

Python importmodule Perl requiremodule

Python frommoduleimport* Java import

module.*Python importmodule Java import

module

frommoduleimport*

5.3.

Python pass Java C( {})

Python Java extends

5.3.1.

Python self C++ Java this self Python self

5.3.2.self__init__

__init__ __init__

5.4.

Python C++ Java new

5.5.UserDict:

Windows ActivePythonIDE File->Locate...(Ctrl-L)

Java Powerbuilder PL/SQL

__init__ __init__

__init__

PythonGuido“ C++ Python”

__init__ AttributeError

Python2.2 Python

UserString UserList UserDict UserDict

Python2.2 dictfileinfo_fromdict.py

5.6.1.

self.attribute self.method

5.7.

Java str1==str2 Python str1is

str2 Java str1.equals(str2) Pythonstr1==str2 Java Java ==Java Python Java str1==str2 objectidentity Python str1isstr2Java str1.equals(str2) Python str1==

str2 Java == Java Python“ ”

“ GetLength” Python __len__“ ”

5.8.

Java Python Python static

Python __init__

Python Python None

5.9.

Python __setitem__ __doc__

6

6.1.

Python try...except raise Java C++ try...catch throw

6.5.Directory

os os.path os.path.splitUNIX,Windows,MacOS Python

7

7.3.

“5”1055

7.4.{n,m}

7.4.1.

M343888

8HTML

8.2.sgmllib.py

Python2.0bug SGMLParser(handle_decl) DOCTYPE Python2.1

Windows ActivePythonIDE“ Runscript”

8.4.BaseHTMLProcessor.py

HTML HTML( JavaScript) HTML(

) BaseHTMLProcessor HTMLSGMLParser SGMLParser

BaseHTMLProcessor( HTML) HTML

8.5.localsglobals

Python2.2:Python( lambda) Python2.2(

lambda) Python2.1 Python2.0 Python

from__future__importnested_scopes

locals globals: getattr

8.6.dictionary

localsdictionary localslocals

9XML

9.2.

__init__.py __init__.py__init__.py

9.6.

XML Python XMLPython XML Python XML XMLPythonPython XML

XML XML XML PythonAttr

10ScriptsStreams

11HTTPWeb

11.6.Last-ModifiedETag

,HTTP Last-Modified ETag,web,,

12SOAPWeb

13

13.2.

Python2.1 unittestPython2.0pyunit.sourceforge.net

14

14.3.roman.py,3

14.5.roman.py,5

15

15.3.

patternpattern

16FunctionalProgramming

16.2.

os.path.abspath

os.path.abspath /usr/os.path.abspath('bin/../local/bin')/usr/local/bin os.path.normpath

os os.path os.path.abspathWindows MacOS os

17

18

18.2.timeit

timeit Pythonhttp://docs.python.org/lib/node396.html

timeit Python hotshot

<< >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

D.1Python

1.3.MacOSXPython

1.1.Python

1.5.RedHatLinuxPython

1.2.RedHatLinux9

1.6.DebianGNU/LinuxPython

1.3.DebianGNU/Linux

1.7.Python

1.4.

1.8.PythonShell

1.5.Shell

2Python

2.1.

2.1.odbchelper.py

2.3.

2.2.buildConnectionStringdocstring

2.4.

2.3.buildConnectionStringdocstring

2.4.1.

2.4.

2.5.

2.5.buildConnectionString2.6.if

3

3.1.1.Dictionary

3.1.Dictionary

3.1.2.Dictionary

3.2.Dictionary3.3.Dictionarykey3.4.dictionary

3.1.3.dictionary

3.5.dictionary

3.2.1.List

3.6.List3.7.list3.8.list(slice)3.9.Slice

3.2.2.list

3.10.list3.11.extend()append()

3.2.3.list

3.12.list

3.2.4.list

3.13.list

3.2.5.list

3.14.List

3.3.Tuple

3.15.tuple3.16.Tuple

3.4.

3.17.myParams

3.4.1.

3.18.

3.4.2.

3.19.3.20.

3.5.

3.21.

3.22.3.23.

3.6.list

3.24.List3.25.keys,valuesitems3.26.buildConnectionStringlist

3.7.list

3.27.odbchelper.py3.28.

4

4.1.

4.1.apihelper.py4.2.apihelper.py4.3.apihelper.py

4.2.

4.4.info

4.3.1.type

4.5.type

4.3.2.str

4.6.str4.7.dir4.8.callable

4.3.3.

4.9.

4.4.getattr

4.10.getattr

4.4.1.getattr

4.11.apihelper.pygetattr

4.4.2.getattr

4.12.getattr4.13.getattr

4.5.

4.14.

4.6.andor

4.15.and4.16.or

4.6.1.and-or

4.17.and-or4.18.and-or4.19.and-or

4.7.lambda

4.20.lambda

4.7.1.lambda

4.21.split

4.8.

4.22.docstring4.23.docstringstr4.24.ljust4.25.

5

5.1.

5.1.fileinfo.py

5.2.frommoduleimport

5.2.importmodulevs.frommoduleimport

5.3.

5.3.Python5.4.FileInfo

5.3.1.

5.5.FileInfoClass5.6.FileInfo

5.4.

5.7.FileInfo

5.4.1.

5.8.

5.5.UserDict:

5.9.UserDict5.10.UserDict5.11.dict

5.6.1.

5.12.__getitem__5.13.__setitem__5.14.MP3FileInfo__setitem__5.15.MP3FileInfoname

5.7.

5.16.UserDict

5.8.

5.17.5.18.

5.9.

5.19.

6

6.1.

6.1.

6.1.1.

6.2.

6.2.

6.3.

6.2.1.

6.4.

6.2.2.

6.5.

6.2.3.I/O

6.6.MP3FileInfo

6.2.4.

6.7.

6.3.for

6.8.for6.9.6.10.dictionary6.11.MP3FileInfofor

6.4.sys.modules

6.12.sys.modules6.13.sys.modules

6.14.__module__6.15.fileinfo.pysys.modules

6.5.Directory

6.16.6.17.6.18.6.19.fileinfo.py6.20.ListingDirectorieswithglob

6.6.

6.21.listDirectory

7

7.2.

7.1.7.2.

7.3.1.

7.3.

7.3.2.

7.4.

7.4.{n,m}

7.5.7.6.Fromntom

7.4.1.

7.7.7.8.{n,m}

7.5.

7.9.(InlineComments)

7.6.:

7.10.7.11.7.12.7.13.7.14.7.15.7.16.()

8HTML

8.1.

8.1.BaseHTMLProcessor.py8.2.dialect.py8.3.dialect.py

8.2.sgmllib.py

8.4.sgmllib.py

8.3.HTML

8.5.urllib

8.6.urllister.py8.7.urllister.py

8.4.BaseHTMLProcessor.py

8.8.BaseHTMLProcessor8.9.BaseHTMLProcessor

8.5.localsglobals

8.10.locals8.11.globals8.12.locals,globals

8.6.dictionary

8.13.dictionary8.14.BaseHTMLProcessor.pydictionary8.15.dictionary

8.7.

8.16.Quotingattributevalues

8.8.dialect.py

8.17.8.18.SGMLParser8.19.handle_data

8.9.

8.20.translate,18.21.translate,2:

8.22.translate,3

9XML

9.1.

9.1.kgp.py9.2.toolbox.py9.3.Sampleoutputofkgp.py9.4.kgp.py

9.2.

9.5.XML()9.6.9.7.

9.3.XML

9.8.XML()9.9.9.10.toxml9.11.9.12.Drillingdownallthewaytotext

9.4.Unicode

9.13.unicode9.14.ASCII9.15.sitecustomize.py9.16.9.17..py9.18.russiansample.xml

9.19.russiansample.xml

9.5.

9.20.binary.xml9.21.getElementsByTagName9.22.9.23.

9.6.

9.24.9.25.

10ScriptsStreams

10.1.

10.1.XML10.2.URLXML10.3.XML ()10.4.StringIO10.5.XML10.6.openAnything10.7.kgp.pyopenAnything

10.2.

10.8.stdoutstderr10.9.10.10.10.11.stderr10.12.

10.13.kgp.py

10.3.

10.14.loadGrammar10.15.ref

10.4.

10.16.

10.5.Creatingseparatehandlersbynodetype

10.17.XML10.18.parse,XML10.19.parse

10.6.

10.20.sys.argv10.21.sys.argv10.22.getopt10.23.kgp.py

11HTTPWeb

11.1.

11.1.openanything.py

11.2.HTTP

11.2.feed

11.4.HTTPweb

11.3.HTTP

11.5.User-Agent

11.4.urllib211.5.Request

11.6.Last-ModifiedETag

11.6.Last-Modified11.7.URL11.8.URL11.9.SupportingETag/If-None-Match

11.7.

11.10.web11.11.11.12.11.13.

11.8.

11.14.11.15.11.16.

11.9.

11.17.openanything11.18.fetch11.19.openanything.py

12SOAPWeb

12.1.

12.1.search.py12.2.search.py

12.2.1.PyXML

12.3.PyXML

12.2.2.fpconst

12.4.fpconst

12.2.3.SOAPpy

12.5.SOAPpy

12.3.SOAP

12.6.

12.4.SOAP

12.7.SOAP

12.6.WSDLSOAP

12.8.12.9.12.10.12.11.WSDLproxySOAP

12.7.Google

12.12.Google

12.13.Google12.14.Google

12.8.SOAP

12.15.Proxy12.16.12.17.12.18.

13

13.3.romantest.py

13.1.romantest.py

13.4.Testingforsuccess

13.2.testToRomanKnownValues

13.5.Testingforfailure

13.3.toRoman13.4.fromRoman

13.6.Testingforsanity

13.5.toRomanfromRoman13.6.

14

14.1.roman.py,1

14.1.roman1.py

14.2.Outputofromantest1.pyagainstroman1.py

14.2.roman.py,2

14.3.roman2.py14.4.toRoman14.5.romantest2.pyroman2.py

14.3.roman.py,3

14.6.roman3.py14.7.toRoman14.8.romantest3.pyroman3.py

14.4.roman.py,4

14.9.roman4.py14.10.fromRoman14.11.romantest4.pyroman4.py

14.5.roman.py,5

14.12.roman5.py14.13.romantest5.pyroman5.py

15

15.1.bugs

15.1.Bug15.2.bugromantest61.py15.3.romantest61.pyroman61.py15.4.Bugroman62.py15.5.romantest62.pyroman62.py

15.2.

15.6.romantest71.py15.7.romantest71.pyroman71.py15.8.roman72.py15.9.romantest72.pyroman72.py

15.3.

15.10.15.11.roman81.py15.12.romantest81.pyroman81.py15.13.roman82.py15.14.romantest82.pyroman82.py15.15.roman83.py15.16.romantest83.pyroman83.py

15.4.

15.17.roman9.py15.18.romantest9.pyroman9.py

16FunctionalProgramming

16.1.

16.1.regression.py16.2.regression.py

16.2.

16.3.fullpath.py16.4.os.path.abspath16.5.fullpath.py

16.6.

16.3.

16.7.filter16.8.regression.pyfilter16.9.

16.4.

16.10.map16.11.map16.12.regression.pymap

16.6.

16.13.16.14.16.15.

16.7.

16.16.regressionTest16.17.1:16.18.2:16.19.3:16.20.4:16.21.5:16.22.6:unittest

17

17.2.plural.py,1

17.1.plural1.py17.2.re.sub17.3.plural1.py17.4.17.5.re.sub

17.3.plural.py,2

17.6.plural2.py17.7.plural

17.4.plural.py,3

17.8.plural3.py

17.5.plural.py,4

17.9.plural4.py17.10.plural4.py17.11.17.12.plural4.py17.13.buildMatchAndApplyFunctions17.14.

17.6.plural.py,5

17.15.rules.en17.16.plural5.py

17.7.plural.py,6

17.17.plural6.py17.18.17.19.

17.20.for17.21.

18

18.1.

18.1.soundex/stage1/soundex1a.py

18.2.timeit

18.2.timeit

18.3.

18.3.soundex/stage1/soundex1e.py

18.4.

18.4.soundex/stage2/soundex2c.py

18.5.

18.5.soundex/stage2/soundex2c.py

<< >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

E.2004-05-20(5.4)

Added12.1“” .Added12.2“SOAP” .Added12.3“SOAP” .Added12.4“SOAP” .Added12.5“WSDL” .Added12.6“WSDLSOAP” .Added12.7“Google” .Added12.8“SOAP” .Added12.9“” .Incorporatedtechnicalreviewerrevisionsin16 FunctionalProgramming and18 .

2004-05-12(5.3)

Addedisalpha()exampleto18.3“” .Thanks,Paul.Incorporatedcopyeditingrevisionsinto5 and6 .FixedURLof9.7“Segue” .

2004-05-09(5.2)

FixedURLof14.1“roman.py,1” .Added18.1“” .Added18.2“timeit” .Added18.3“” .Added18.4“” .Added18.5“” .Added18.6“” .

Added18.7“” .

2004-05-05(5.1)

Clarified7.7“” and7.8“{n,m}” .Clarified7.10“” .Fixedtypoin11.6“Last-Modified” .Thanks,Jesir.Fixedtypoin3.11“extend()append()” .Thanks,Daniel.Incorporatedtechnicalreviewerrevisions.Incorporatedcopyeditorrevisionsin1 Python ,2 Python ,3 ,and4 .

2004-04-16(5.0)

Added11.1“” .Added11.2“HTTP” .Added11.3“HTTP” .Added11.4“HTTPweb” .Added11.5“User-Agent” .Added11.6“Last-ModifiedETag” .Added11.7“” .Added11.8“” .Added11.9“” .Added11.10“” .Added3.11“extend()append()” .ChangeddescriptionsofhowtodownloadPythonthroughout1Pythontobemoregenericandlessversion-specific.Changedreferencesof“module”to“program”in2.1“” and2.4“” sincewehaven'texplainedmodulesyet.Addedexplicitinstructionsin2.4“” forthereadertoopentheirPythonIDEandfollowalongwiththeexamples.Changedallexamplesanddescriptionsthatreferredtotruthvalues1and0

torefertoTrueandFalse.Updated3.22“” toshownewPython2.3TypeErrormessage.Fixedtypoin17.19“” .Fixedtypoin7.7“” .Fixedtypoin17.9“plural4.py”.

2004-03-25(4.9)

Finished16.7“” .Added16.8“” .Splitunittestingintroductionintotwochapters,13 and14 .Fixedtypoin17.12“plural4.py” .Fixedtypoin17.18“” .

2004-03-25(4.8)

Finished17.7“plural.py,6” .Finished17.8“” .FixedbrokenlinksinA,,B,,C,,D,.

2004-03-21(4.7)

Added17.1“” .Added17.2“plural.py,1” .Added17.3“plural.py,2” .Added17.4“plural.py,3” .Added17.5“plural.py,4” .Added17.6“plural.py,5” .Added17.7“plural.py,6” (unfinished).Added17.8“” (unfinished).

2004-03-14(4.6)

Finished7.4“{n,m}” .Finished7.5“” .Finished7.6“:” .Expanded7.7“” .

2004-03-07(4.5)

Added7.1“” .Added7.4“{n,m}” (incomplete).Added7.5“” (incomplete).Added7.6“:” (incomplete).Added7.7“” .Moved7.2“” and7.3“” toregularexpressionschapter.Added6.20“ListingDirectorieswithglob”.Added6.7“” .Added5.11“dict” .Added10.11“stderr” .Added4.12“getattr” and4.13“getattr” .Added2.6“if” .Added3.23“” .Split5 into2chapters:5 and6 .Split9 XMLinto2chapters:9 XMLand10 ScriptsStreams.Split13 into2chapters:13 and15 .Renamedhelptoinfoin4 .Fixedincorrectback-referencein8.5“localsglobals” .Fixedbrokenexamplelinksin8.1“” .Fixedmissinglineinexamplein9.1“” .Fixedtypoin8.2“sgmllib.py” .

2003-10-08(4.4)

Added1.1“Python” .Added1.2“WindowsPython” .Added1.3“MacOSXPython” .Added1.4“MacOS9Python” .Added1.5“RedHatLinuxPython” .Added1.6“DebianGNU/LinuxPython” .Added1.7“Python” .Added1.9“” .Removedpreface.Fixedtypoin3.27“odbchelper.py” .AddedlinktoPEP257in2.3“” .FixedlinktoHowtoThinkLikeaComputerScientistin3.4.2“” .Addednoteaboutimpliedassertin3.3“Tuple” .

2003-09-28(4.3)

Added16.6“” .Added16.7“” (incomplete).FixedlinksinF,.

2003-09-17(4.2.1)

Fixedlinksonindexpage.Fixedsyntaxhighlighting.

2003-09-12(4.2)

Fixedtyposin16.4“” ,16.3“” ,7.2“” ,and10.6“” .Thanks,Doug.Fixedexternallinkin5.3“” .Thanks,Harry.Changedwordingattheendof4.5“” .Thanks,Paul.

Addedsentencein13.5“Testingforfailure” tomakeitclearerthatwe'repassingafunctiontoassertRaises,notafunctionnameasastring.Thanks,Stephen.Fixedtypoin8.8“dialect.py” .Thanks,Wellie.Fixedlinkstodialectizedexamples.FixedexternallinktothehistoryofRomannumerals.ThankstomanyconcernedRomannumeralfansaroundtheworld.

2002-07-28(4.1)

Added10.3“” .Added10.4“” .Added10.5“Creatingseparatehandlersbynodetype” .Added10.6“” .Added10.7“” .Added10.8“” .Fixedtypoin6.5“Directory” .It'sos.getcwd(),notos.path.getcwd().Thanks,Abhishek.Fixedtypoin3.7“list” .Whenevaluated(insteadofprinted),thePythonIDEwilldisplaysinglequotesaroundtheoutput.Changedstrexamplein4.8“” touseauser-definedfunction,sincePython2.2obsoletedtheoldexamplebydefiningadocstringforthebuilt-indictionarymethods.ThanksEric.Fixedtypoin9.4“Unicode” ,"anyway"to"anywhere".ThanksFrank.Fixedtypoin13.6“Testingforsanity” ,doubledword"accept".ThanksRalph.Fixedtypoin15.3“” ,C?C?C?matches0to3Ccharacters,not4.ThanksRalph.Clarifiedandexpandedexplanationofimpliedsliceindicesin3.9“Slice” .ThanksPetr.Addedhistoricalnotein5.5“UserDict:” nowthatPython2.2

supportssubclassingbuilt-indatatypesdirectly.Addedexplanationofupdatedictionarymethodin5.9“UserDict” .ThanksPetr.ClarifiedPython'slackofoverloadingin5.5“UserDict:” .ThanksPetr.Fixedtypoin8.8“BaseHTMLProcessor” .HTMLcommentsendwithtwodashesandabracket,notone.ThanksPetr.Changedtenseofnoteaboutnestedscopesin8.5“localsglobals”nowthatPython2.2isout.ThanksPetr.Fixedtypoin8.14“BaseHTMLProcessor.pydictionary” ;aspaceshouldhavebeenanon-breakingspace.ThanksPetr.Addedtitletonoteonderivedclassesin5.5“UserDict:” .ThanksPetr.Addedtitletonoteondownloadingunittestin15.3“” .ThanksPetr.Fixedtypesettingproblemin16.6“” ;tabsshouldhavebeenspaces,andthelinenumbersweremisaligned.ThanksPetr.Fixedcapitalizationtypointhetipontruthvaluesin3.2“List” .It'sTrueandFalse,nottrueandfalse.Thankstoeveryonewhopointedthisout.Changedsectiontitlesof3.1“Dictionary” ,3.2“List” ,and3.3“Tuple” ."Dictionaries101"wasacutewayofsayingthatthissectionwasanbeginner'sintroductiontodictionaries.Americancollegestendtousethisnumberingschemetoindicateintroductorycourseswithnoprerequisites,butapparentlythisisadistinctlyAmericantradition,anditwasunnecessarilyconfusingmyinternationalreaders.Inmydefense,whenIinitiallywrotethesesectionsayearandahalfago,itneveroccurredtomethatIwouldhaveinternationalreaders.Upgradedtoversion1.52oftheDocBookXSLstylesheets.Upgradedtoversion6.52ofMichaelKay SAXONXSLT.

Variousaccessibility-relatedstylesheettweaks.Somewherebetweenthisrevisionandthelastone,shesaidyes.Theweddingwillbenextspring.

2002-04-26(4.0-2)

Fixedtypoin4.15“and” .Fixedtypoin2.4“” .FixedWindowshelpfile(missingtableofcontentsduetobasestylesheetchanges).

2002-04-19(4.0)

Expanded2.4“” toincludemoreaboutimportsearchpaths.Fixedtypoin3.7“list” .ThankstoBrianforthecorrection.Rewrotethetipontruthvaluesin3.2“List” ,nowthatPythonhasaseparatebooleandatatype.Fixedtypoin5.2“frommoduleimport” whencomparingsyntaxtoJava.ThankstoRickforthecorrection.Addednotein5.5“UserDict:” aboutderivedclassesalwaysoverridingancestorclasses.Fixedtypoin5.18“” .ThankstoKevinforthecorrection.Addednotein6.1“” thatyoucandefineandraiseyourownexceptions.ThankstoRonyforthesuggestion.Fixedtypoin8.17“” .ThanksforRickforthecorrection.Addednotein8.18“SGMLParser”aboutwhatthereturncodesmean.ThankstoHowardforthesuggestion.AddedstrfunctionwhencreatingStringIOinstancein10.6“openAnything”.ThankstoGanesanfortheidea.Addedlinkin13.3“romantest.py” toexplanationofwhytestcasesbelonginaseparatefile.Changed16.2“” touseos.path.dirnameinsteadofos.path.split.

ThankstoMarcfortheidea.Addedcodesamples(piglatin.py,parsephone.py,andplural.py)fortheupcomingregularexpressionschapter.UpdatedandexpandedlistofPythondistributionsonhomepage.

2002-01-01(3.9)

Added9.4“Unicode” .Added9.5“” .Added9.6“” .Added10.1“” .Added10.2“” .Addedsimplecounterforloopexamples(goodusageandbadusage)in6.3“for” .ThankstoKevinfortheidea.Fixedtypoin3.25“keys,valuesitems” (twoelementsofparams.values()werereversed).Fixedmistakein4.3“typestrdir” withregardstothenameofthe__builtin__module.ThankstoDenisforthecorrection.Addedadditionalexamplein16.2“” toshowhowtorununittestsinthecurrentworkingdirectory,insteadofthedirectorywhereregression.pyislocated.Modifiedexplanationofhowtoderiveanegativelistindexfromapositivelistindexin3.7“list” .ThankstoRenauldforthesuggestion.UpdatedlinksonhomepagefordownloadinglatestversionofPython.AddedlinkonhomepagetoBruceEckel'spreliminarydraftofThinkinginPython,amarvelous(andadvanced)bookondesignpatternsandhowtoimplementtheminPython.

2001-11-18(3.8)

Added16.2“” .

Added16.3“” .Added16.4“” .Added16.5“” .Expandedsampleoutputin16.1“” .Finished9.3“XML” .

2001-09-30(3.7)

Added9.2“” .Added9.3“XML” .Cleanedupintroductoryparagraphin9.1“” .ThankstoMattforthissuggestion.AddedJavatipin5.2“frommoduleimport” .ThankstoOriforthissuggestion.Fixedmistakein4.8“” whereIimpliedthatyoucouldnotuseisNonetocomparetoanullvalueinPython.Infact,youcan,andit'sfasterthan==None.ThankstoOripointingthisout.Clarifiedin3.2“List” whereIsaidthatli=li+otherwasequivalenttoli.extend(other).Theresultisthesame,butextendisfasterbecauseitdoesn'tcreateanewlist.ThankstoDenispointingthisout.Fixedmistakein3.2“List” whereIsaidthatli+=otherwasequivalenttoli=li+other.Infact,it'sequivalenttoli.extend(other),sinceitdoesn'tcreateanewlist.ThankstoDenispointingthisout.Fixedtypographicallazinessin2 Python ;whenIwaswritingit,Ihadnotyetstandardizedonputtingstringliteralsinsinglequoteswithinthetext.Theyweresetoffbytypography,butthisislostinsomerenditionsofthebook(likeplaintext),makingitdifficulttoread.ThankstoDenisforthissuggestion.Fixedmistakein2.2“” whereIsaidthatstaticallytypedlanguages

alwaysuseexplicitvariable+datatypedeclarationstoenforcestatictyping.Mostdo,buttherearesomestaticallytypedlanguageswherethecompilerfiguresoutwhattypethevariableisbasedonusagewithinthecode.ThankstoTonyforpointingthisout.AddedlinktoSpanishtranslation.

2001-09-06(3.6.4)

AddedcodeinBaseHTMLProcessortohandlenon-HTMLentityreferences,andaddedanoteaboutitin8.4“BaseHTMLProcessor.py” .Modified8.11“globals” toincludehtmlentitydefsintheoutput.

2001-09-04(3.6.3)

Fixedtypoin9.1“” .AddedlinktoKoreantranslation.

2001-08-31(3.6.2)

Fixedtypoin13.6“Testingforsanity” (thelastrequirementwaslistedtwice).

2001-08-31(3.6)

Finished8 HTMLwith8.9“” and8.10“” .Added15.4“” .Started9 XMLwith9.1“” .Started16 FunctionalProgramming with16.1“” .Fixedlong-standingbugincolorizingscriptthatimproperlycolorizedtheexamplesin8 HTML.AddedlinktoFrenchtranslation.TheydidtherightthingandtranslatedthesourceXML,sotheycanre-useallmybuildscriptsandmaketheirworkavailableinsixdifferentformats.

Upgradedtoversion1.43oftheDocBookXSLstylesheets.Upgradedtoversion6.43ofMichaelKay SAXONXSLT.Massivestylesheetchanges,movingawayfromatable-basedlayoutandtowardsmoreappropriateuseofcascadingstylesheets.Unfortunately,CSShasasmanycompatibilityproblemsasanythingelse,sotherearestillsometablesusedintheheaderandfooter.TheresultingHTMLversionlooksworseinNetscape4,butbetterinmodernbrowsers,includingNetscape6,Mozilla,InternetExplorer5,Opera5,Konqueror,andiCab.Andit'sstillcompletelyreadableinLynx.IloveLynx.Itwasmyfirstwebbrowser.Youneverforgetyourfirst.MovedtoAnttohavebettercontroloverthebuildprocess,whichisespeciallyimportantnowthatI'mjugglingsixoutputformatsandtwolanguages.Consolidatedtheavailabledownloadablearchives;previously,Ihaddifferentfilesforeachplatform,becausethe.zipfilesthatPython'szipfilemodulecreatesarenon-standardandcan'tbeopenedbyAladdinExpanderonMacOS.Butthe.zipfilesthatAntcreatesarecompletelystandardandcross-platform.GoAnt!NowhostingthecompleteXMLsource,XSLstylesheets,andassociatedscriptsandlibrariesonSourceForge.There'salsoCVSaccessforthereallyadventurous.Re-licensedtheexamplecodeunderthenew-and-improvedGPL-compatiblePython2.1.1license.Thanks,Guido;peoplereallydocare,anditreallydoesmatter.

2001-06-26(3.5)

Addedexplanationofstrong/weak/static/dynamicdatatypesin2.2“” .Addedcase-sensitivityexamplein3.1“Dictionary” .Useos.path.normcasein5 tocompensateforinferioroperating

systemswhosefilesaren'tcase-sensitive.FixedindentationproblemsincodesamplesinPDFversion.

2001-05-31(3.4)

Added14.5“roman.py,5” .Added15.1“bugs” .Added15.2“” .Added15.3“” .Added15.5“” .Fixedyetanotherstylesheetbugthatwasdroppingnested</span>tags.

2001-05-24(3.3)

Added13.2“” .Added13.3“romantest.py” .Added13.4“Testingforsuccess” .Added13.5“Testingforfailure” .Added13.6“Testingforsanity” .Added14.1“roman.py,1” .Added14.2“roman.py,2” .Added14.3“roman.py,3” .Added14.4“roman.py,4” .TweakedstylesheetsinanendlessquestforcompleteNetscape/Mozillacompatibility.

2001-05-03(3.2)

Added8.8“dialect.py” .Added7.2“” .Fixedbuginhandle_declmethodthatwouldproduceincorrectdeclarations(addingaspacewhereitcouldn'tbe).

FixedbuginCSS(introducedin2.9)wherebodybackgroundcolorwasmissing.

2001-04-18(3.1)

AddedcodeinBaseHTMLProcessor.pytohandledeclarations,nowthatPython2.1supportsthem.Addednoteaboutnestedscopesin8.5“localsglobals” .Fixedobscurebugin8.1“BaseHTMLProcessor.py”whereattributevalueswithcharacterentitieswouldnotbeproperlyescaped.Nowrecommending(butnotrequiring)Python2.1,duetoitssupportofdeclarationsinsgmllib.py.UpdateddownloadlinksonthehomepagetopointtoPython2.1,whereavailable.Movedtoversionedfilenames,tohelppeoplewhoredistributethebook.

2001-04-16(3.0)

Fixedminorbugincodelistingin8 HTML.AddedlinktoChinesetranslationonhomepage.

2001-04-13(2.9)

Added8.5“localsglobals” .Added8.6“dictionary” .Tightenedcodein8 HTML,specificallyChefDialectizer,tousefewerandsimplerregularexpressions.FixedastylesheetbugthatwasinsertingblankpagesbetweenchaptersinthePDFversion.FixedascriptbugthatwasstrippingtheDOCTYPEfromthehomepage.AddedlinktoPythonCookbook,andaddedafewlinkstoindividualrecipesinA,.

SwitchedtoGoogleforsearchingonhttp://diveintopython.org/.Upgradedtoversion1.36oftheDocBookXSLstylesheets,whichwasmuchmoredifficultthanitsounds.Theremaystillbelingeringbugs.

2001-03-26(2.8)

Added8.3“HTML” .Added8.4“BaseHTMLProcessor.py” .Added8.7“” .Tightenedupcodein4 ,usingthebuilt-infunctioncallableinsteadofmanuallycheckingtypes.Moved5.2“frommoduleimport” from4 to5 .Fixedtypoincodeexamplein5.1“” (addedcolon).Addedseveraladditionaldownloadableexamplescripts.AddedWindowsHelpoutputformat.

2001-03-16(2.7)

Added8.2“sgmllib.py” .Tightenedupcodein8 HTML.Changedcodein2 Python touseitemsmethodinsteadofkeys.Moved3.4.2“” sectionto2 Python .Editednoteaboutjoinstringmethod,andprovidedalinktothenewentryinTheWholePythonFAQthatexplainswhyjoinisastringmethodinsteadofalistmethod.Rewrote4.6“andor” toemphasizethefundamentalnatureofandandorandde-emphasizetheand-ortrick.Reorganizedlanguagecomparisonsintonotes.

2001-02-28(2.6)

ThePDFandWordversionsnowhavecolorizedexamples,animproved

tableofcontents,andproperlyindentedtipsandnotes.TheWordversionisnowinnativeWordformat,compatiblewithWord97.ThePDFandtextversionsnowhavefewerproblemswithimproperlyconvertedspecialcharacters(liketrademarksymbolsandcurlyquotes).AddedlinktodownloadWordversionforUNIX,incasesometwistedsoulwantstoimportitintoStarOfficeorsomething.Fixedseveralnoteswhichweremissingtitles.FixedstylesheetstoworkaroundbuginInternetExplorer5forMacOSwhichcausedcolorizedwordsintheexamplestobedisplayedinthewrongfont.(Hello?!?Microsoft?Whichpartof<pre>don'tyouunderstand?)FixedarchivecorruptioninMacOSdownloads.Infirstsectionofeachchapter,addedlinktodownloadexamples.(Myaccesslogsshowthatpeopleskimorskipthetwopageswheretheycouldhavedownloadedthem(thehomepageandpreface),thenscrambletofindadownloadlinkoncetheyactuallystartreading.)Tightenedthehomepageandprefaceevenmore,inthehopesthatsomedaysomeonewillreadthem.SoonIhopetogetbacktoactuallywritingthisbookinsteadofdebuggingit.

2001-02-23(2.5)

Added6.4“sys.modules” .Added6.5“Directory” .Moved6.17“” from3.4.2“” to6.5“Directory” .Added6.6“” .Added5.10“” .Added8.1“” .Fixedprogramlistingin6.10“dictionary” whichwasmissingacolon.

2001-02-12(2.4.1)

Changednewsgrouplinkstouse“news:”protocol,nowthatdeja.comisdefunct.Addedfilesizestodownloadlinks.

2001-02-12(2.4)

Added“furtherreading”linksinmostsections,andcollatedtheminA,.AddedURLsinparenthesesnexttoexternallinksintextversion.

2001-02-09(2.3)

Rewrotesomeofthecodein5 touseclassattributesandabetterexampleofmulti-variableassignment.Reorganized5 toputtheclasssectionsfirst.Added5.8“” .Added6.1“” .Added6.2“” .Mergedthe“review”sectionin5 into5.1“” .Colorizedallprogramlistingsandexamples.Fixedimportanterrorin2.2“” :functionsthatdonotexplicitlyreturnavaluereturnNone,soyoucanassignthereturnvalueofsuchafunctiontoavariablewithoutraisinganexception.Addedminorclarificationsto2.3“” ,2.4“” ,and3.4“” .

2001-02-02(2.2)

Edited4.4“getattr” .Addedtitlestoxreftags,sotheycanhavetheircutelittletooltipstoo.Changedthelookoftherevisionhistorypage.FixedproblemIintroducedyesterdayinmyHTMLpost-processingscriptthatwascausinginvalidHTMLcharacterreferencesandbreakingsome

browsers.Upgradedtoversion1.29oftheDocBookXSLstylesheets.

2001-02-01(2.1)

Rewrotetheexamplecodeof4 tousegetattrinsteadofexecandeval,andrewroteexplanatorytexttomatch.Addedexampleoflistoperatorsin3.2“List” .Addedlinkstorelevantsectionsinthesummarylistsattheendofeachchapter(3.8“” and4.9“” ).

2001-01-31(2.0)

Split5.6“” intothreesections,5.5“UserDict:” ,5.6“” ,and5.7“” .ChangednotesongarbagecollectiontopointoutthatPython2.0andlatercanhandlecircularreferenceswithoutadditionalcoding.FixedUNIXdownloadstoincludeallrelevantfiles.

2001-01-15(1.9)

Removedintroductionto2 Python .Removedintroductionto4 .Removedintroductionto5 .Editedtextruthlessly.Itendtoramble.

2001-01-12(1.8)

Addedmoreexamplesto3.4.2“” .Added5.3“” .Added5.4“” .Added5.6“” .Moreminorstylesheettweaks,includingaddingtitlestolinktags,which,

ifyourbrowseriscoolenough,willdisplayadescriptionofthelinktargetinacutelittletooltip.

2001-01-03(1.71)

Madeseveralmodificationstostylesheetstoimprovebrowsercompatibility.

2001-01-02(1.7)

Addedintroductionto2 Python .Addedintroductionto4 .Addedreviewsectionto5 [laterremoved]Added5.9“” .Added6.3“for” .Added3.4.2“” .Wrotescriptstoconvertbooktonewoutputformats:onesingleHTMLfile,PDF,MicrosoftWord97,andplaintext.Registeredthediveintopython.orgdomainandmovedthebookthere,alongwithlinkstodownloadthebookinallavailableoutputformatsforofflinereading.ModifiedtheXSLstylesheetstochangetheheaderandfooternavigationthatdisplaysoneachpage.Thetopofeachpageisbrandedwiththedomainnameandbookversion,followedbyabreadcrumbtrailtojumpbacktothechaptertableofcontents,themaintableofcontents,orthesitehomepage.

2000-12-11(1.6)

Added4.8“” .Finished4 with4.9“” .Started5 with5.1“” .

2000-11-22(1.5)

Added4.6“andor” .Added4.7“lambda” .Addedappendixthatlistssectionabstracts.Addedappendixthatliststips.Addedappendixthatlistsexamples.Addedappendixthatlistsrevisionhistory.Expandedexampleofmappinglistsin3.6“list” .Encapsulatedseveralmorecommonphrasesintoentities.Upgradedtoversion1.25oftheDocBookXSLstylesheets.

2000-11-14(1.4)

Added4.5“” .Addeddirdocumentationto4.3“typestrdir” .Addedinexamplein3.3“Tuple” .Addedadditionalnoteaboutif__name__trickunderMacPython.SwitchedtoMichaelKay SAXONXSLT.Upgradedtoversion1.24oftheDocBookXSLstylesheets.Addeddb-htmlprocessinginstructionswithexplicitfilenamesofeachchapterandsection,toallowdeeplinkstocontentevenifIaddorre-arrangesectionslater.Madeseveralcommonphrasesintoentitiesforeasierreuse.Changedseveralliteraltagstoconstant.

2000-11-09(1.3)

Addedsectionondynamiccodeexecution.Addedlinkstorelevantsection/examplewhereverIrefertopreviouslycoveredconcepts.Expandedintroductionofchapter2toexplainwhatthefunctionactually

does.ExplicitlyplacedexamplecodeundertheGNUGeneralPublicLicenseandaddedappendixtodisplaylicense.[Note8/16/2001:codehasbeenre-licensedunderGPL-compatiblePythonlicense]Changedlinkstolicensestousexreftags,nowthatIknowhowtousethem.

2000-11-06(1.2)

Addedfirstfoursectionsofchapter2.Tightenedupprefaceevenmore,andaddedlinktoMacOSversionofPython.Filledoutexamplesin"Mappinglists"and"Joiningstrings"toshowlogicalprogression.Addedoutputinchapter1summary.

2000-10-31(1.1)

Finishedchapter1withsectionsonmappingandjoining,andachaptersummary.Toneddownthepreface,addedlinkstointroductionsfornon-programmers.Fixedseveraltypos.

2000-10-30(1.0)

Initialpublication

<< >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

F. Emacs DocBookXML, NormanWalsh XSLMichaelKay SAXONXSLT HTML, HTMLDoc PDF; w3m(plaintext) XML,htmlhtmlflatHTMLHelpWorkshopchmJustvanRossum pyfontify.py

DocBook, XML , XSL, DocBook:TheDefinitiveGuide DocBook, DocBook

<< GNUFreeDocumentationLicense>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>GNUFreeDocumentationLicense <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

G.GNUFreeDocumentationLicenseG.0.PreambleG.1.ApplicabilityanddefinitionsG.2.VerbatimcopyingG.3.CopyinginquantityG.4.ModificationsG.5.CombiningdocumentsG.6.CollectionsofdocumentsG.7.AggregationwithindependentworksG.8.TranslationG.9.TerminationG.10.FuturerevisionsofthislicenseG.11.HowtousethisLicenseforyourdocuments

Version1.1,March2000

Copyright(C)2000FreeSoftwareFoundation,Inc.59TemplePlace,Suite330,Boston,MA02111-1307USAEveryoneispermittedtocopyanddistributeverbatimcopiesofthislicensedocument,butchangingitisnotallowed.

G.0.PreambleThepurposeofthisLicenseistomakeamanual,textbook,orotherwrittendocument"free"inthesenseoffreedom:toassureeveryonetheeffectivefreedomtocopyandredistributeit,withorwithoutmodifyingit,eithercommerciallyornoncommercially.Secondarily,thisLicensepreservesfortheauthorandpublisherawaytogetcreditfortheirwork,whilenotbeingconsideredresponsibleformodificationsmadebyothers.

ThisLicenseisakindof"copyleft",whichmeansthatderivativeworksofthedocumentmustthemselvesbefreeinthesamesense.ItcomplementstheGNUGeneralPublicLicense,whichisacopyleftlicensedesignedforfreesoftware.

WehavedesignedthisLicenseinordertouseitformanualsforfreesoftware,becausefreesoftwareneedsfreedocumentation:afreeprogramshouldcomewithmanualsprovidingthesamefreedomsthatthesoftwaredoes.ButthisLicenseisnotlimitedtosoftwaremanuals;itcanbeusedforanytextualwork,regardlessofsubjectmatterorwhetheritispublishedasaprintedbook.WerecommendthisLicenseprincipallyforworkswhosepurposeisinstructionorreference.

<< 123456789101112

Applicabilityanddefinitions>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>GNUFreeDocumentationLicense>Applicabilityanddefinitions <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

G.1.ApplicabilityanddefinitionsThisLicenseappliestoanymanualorotherworkthatcontainsanoticeplacedbythecopyrightholdersayingitcanbedistributedunderthetermsofthisLicense.The"Document",below,referstoanysuchmanualorwork.Anymemberofthepublicisalicensee,andisaddressedas"you".

A"ModifiedVersion"oftheDocumentmeansanyworkcontainingtheDocumentoraportionofit,eithercopiedverbatim,orwithmodificationsand/ortranslatedintoanotherlanguage.

A"SecondarySection"isanamedappendixorafront-mattersectionoftheDocumentthatdealsexclusivelywiththerelationshipofthepublishersorauthorsoftheDocumenttotheDocument'soverallsubject(ortorelatedmatters)andcontainsnothingthatcouldfalldirectlywithinthatoverallsubject.(Forexample,iftheDocumentisinpartatextbookofmathematics,aSecondarySectionmaynotexplainanymathematics.)Therelationshipcouldbeamatterofhistoricalconnectionwiththesubjectorwithrelatedmatters,oroflegal,commercial,philosophical,ethicalorpoliticalpositionregardingthem.

The"InvariantSections"arecertainSecondarySectionswhosetitlesaredesignated,asbeingthoseofInvariantSections,inthenoticethatsaysthattheDocumentisreleasedunderthisLicense.

The"CoverTexts"arecertainshortpassagesoftextthatarelisted,asFront-CoverTextsorBack-CoverTexts,inthenoticethatsaysthattheDocumentisreleasedunderthisLicense.

A"Transparent"copyoftheDocumentmeansamachine-readablecopy,representedinaformatwhosespecificationisavailabletothegeneralpublic,whosecontentscanbeviewedandediteddirectlyandstraightforwardlywith

generictexteditorsor(forimagescomposedofpixels)genericpaintprogramsor(fordrawings)somewidelyavailabledrawingeditor,andthatissuitableforinputtotextformattersorforautomatictranslationtoavarietyofformatssuitableforinputtotextformatters.AcopymadeinanotherwiseTransparentfileformatwhosemarkuphasbeendesignedtothwartordiscouragesubsequentmodificationbyreadersisnotTransparent.Acopythatisnot"Transparent"iscalled"Opaque".

ExamplesofsuitableformatsforTransparentcopiesincludeplainASCIIwithoutmarkup,Texinfoinputformat,LaTeXinputformat,SGMLorXMLusingapubliclyavailableDTD,andstandard-conformingsimpleHTMLdesignedforhumanmodification.OpaqueformatsincludePostScript,PDF,proprietaryformatsthatcanbereadandeditedonlybyproprietarywordprocessors,SGMLorXMLforwhichtheDTDand/orprocessingtoolsarenotgenerallyavailable,andthemachine-generatedHTMLproducedbysomewordprocessorsforoutputpurposesonly.

The"TitlePage"means,foraprintedbook,thetitlepageitself,plussuchfollowingpagesasareneededtohold,legibly,thematerialthisLicenserequirestoappearinthetitlepage.Forworksinformatswhichdonothaveanytitlepageassuch,"TitlePage"meansthetextnearthemostprominentappearanceofthework'stitle,precedingthebeginningofthebodyofthetext.

<<GNUFreeDocumentationLicense 1234567891011

12 Verbatimcopying>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>GNUFreeDocumentationLicense>Verbatimcopying <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

G.2.VerbatimcopyingYoumaycopyanddistributetheDocumentinanymedium,eithercommerciallyornoncommercially,providedthatthisLicense,thecopyrightnotices,andthelicensenoticesayingthisLicenseappliestotheDocumentarereproducedinallcopies,andthatyouaddnootherconditionswhatsoevertothoseofthisLicense.Youmaynotusetechnicalmeasurestoobstructorcontrolthereadingorfurthercopyingofthecopiesyoumakeordistribute.However,youmayacceptcompensationinexchangeforcopies.Ifyoudistributealargeenoughnumberofcopiesyoumustalsofollowtheconditionsinsection3.

Youmayalsolendcopies,underthesameconditionsstatedabove,andyoumaypubliclydisplaycopies.

<<Applicabilityanddefinitions 1234567891011

12 Copyinginquantity>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>GNUFreeDocumentationLicense>Copyinginquantity <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

G.3.CopyinginquantityIfyoupublishprintedcopiesoftheDocumentnumberingmorethan100,andtheDocument'slicensenoticerequiresCoverTexts,youmustenclosethecopiesincoversthatcarry,clearlyandlegibly,alltheseCoverTexts:Front-CoverTextsonthefrontcover,andBack-CoverTextsonthebackcover.Bothcoversmustalsoclearlyandlegiblyidentifyyouasthepublisherofthesecopies.Thefrontcovermustpresentthefulltitlewithallwordsofthetitleequallyprominentandvisible.Youmayaddothermaterialonthecoversinaddition.Copyingwithchangeslimitedtothecovers,aslongastheypreservethetitleoftheDocumentandsatisfytheseconditions,canbetreatedasverbatimcopyinginotherrespects.

Iftherequiredtextsforeithercoveraretoovoluminoustofitlegibly,youshouldputthefirstoneslisted(asmanyasfitreasonably)ontheactualcover,andcontinuetherestontoadjacentpages.

IfyoupublishordistributeOpaquecopiesoftheDocumentnumberingmorethan100,youmusteitherincludeamachine-readableTransparentcopyalongwitheachOpaquecopy,orstateinorwitheachOpaquecopyapublicly-accessiblecomputer-networklocationcontainingacompleteTransparentcopyoftheDocument,freeofaddedmaterial,whichthegeneralnetwork-usingpublichasaccesstodownloadanonymouslyatnochargeusingpublic-standardnetworkprotocols.Ifyouusethelatteroption,youmusttakereasonablyprudentsteps,whenyoubegindistributionofOpaquecopiesinquantity,toensurethatthisTransparentcopywillremainthusaccessibleatthestatedlocationuntilatleastoneyearafterthelasttimeyoudistributeanOpaquecopy(directlyorthroughyouragentsorretailers)ofthateditiontothepublic.

Itisrequested,butnotrequired,thatyoucontacttheauthorsoftheDocumentwellbeforeredistributinganylargenumberofcopies,togivethemachancetoprovideyouwithanupdatedversionoftheDocument.

<<Verbatimcopying 123456789101112 Modifications>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>GNUFreeDocumentationLicense>Modifications <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

G.4.ModificationsYoumaycopyanddistributeaModifiedVersionoftheDocumentundertheconditionsofsections2and3above,providedthatyoureleasetheModifiedVersionunderpreciselythisLicense,withtheModifiedVersionfillingtheroleoftheDocument,thuslicensingdistributionandmodificationoftheModifiedVersiontowhoeverpossessesacopyofit.Inaddition,youmustdothesethingsintheModifiedVersion:

1. UseintheTitlePage(andonthecovers,ifany)atitledistinctfromthatoftheDocument,andfromthoseofpreviousversions(whichshould,iftherewereany,belistedintheHistorysectionoftheDocument).Youmayusethesametitleasapreviousversioniftheoriginalpublisherofthatversiongivespermission.

2. ListontheTitlePage,asauthors,oneormorepersonsorentitiesresponsibleforauthorshipofthemodificationsintheModifiedVersion,togetherwithatleastfiveoftheprincipalauthorsoftheDocument(allofitsprincipalauthors,ifithaslessthanfive).

3. StateontheTitlepagethenameofthepublisheroftheModifiedVersion,asthepublisher.

4. PreserveallthecopyrightnoticesoftheDocument.5. Addanappropriatecopyrightnoticeforyourmodificationsadjacenttothe

othercopyrightnotices.6. Include,immediatelyafterthecopyrightnotices,alicensenoticegivingthe

publicpermissiontousetheModifiedVersionunderthetermsofthisLicense,intheformshownintheAddendumbelow.

7. PreserveinthatlicensenoticethefulllistsofInvariantSectionsandrequiredCoverTextsgivenintheDocument'slicensenotice.

8. IncludeanunalteredcopyofthisLicense.9. Preservethesectionentitled"History",anditstitle,andaddtoitanitem

statingatleastthetitle,year,newauthors,andpublisheroftheModifiedVersionasgivenontheTitlePage.Ifthereisnosectionentitled"History"intheDocument,createonestatingthetitle,year,authors,andpublisheroftheDocumentasgivenonitsTitlePage,thenaddanitemdescribingtheModifiedVersionasstatedintheprevioussentence.

10. Preservethenetworklocation,ifany,givenintheDocumentforpublicaccesstoaTransparentcopyoftheDocument,andlikewisethenetworklocationsgivenintheDocumentforpreviousversionsitwasbasedon.Thesemaybeplacedinthe"History"section.YoumayomitanetworklocationforaworkthatwaspublishedatleastfouryearsbeforetheDocumentitself,oriftheoriginalpublisheroftheversionitreferstogivespermission.

11. Inanysectionentitled"Acknowledgements"or"Dedications",preservethesection'stitle,andpreserveinthesectionallthesubstanceandtoneofeachofthecontributoracknowledgementsand/ordedicationsgiventherein.

12. PreservealltheInvariantSectionsoftheDocument,unalteredintheirtextandintheirtitles.Sectionnumbersortheequivalentarenotconsideredpartofthesectiontitles.

13. Deleteanysectionentitled"Endorsements".SuchasectionmaynotbeincludedintheModifiedVersion.

14. Donotretitleanyexistingsectionas"Endorsements"ortoconflictintitlewithanyInvariantSection.

IftheModifiedVersionincludesnewfront-mattersectionsorappendicesthatqualifyasSecondarySectionsandcontainnomaterialcopiedfromtheDocument,youmayatyouroptiondesignatesomeorallofthesesectionsasinvariant.Todothis,addtheirtitlestothelistofInvariantSectionsintheModifiedVersion'slicensenotice.Thesetitlesmustbedistinctfromanyothersectiontitles.

Youmayaddasectionentitled"Endorsements",provideditcontainsnothingbut

endorsementsofyourModifiedVersionbyvariousparties--forexample,statementsofpeerrevieworthatthetexthasbeenapprovedbyanorganizationastheauthoritativedefinitionofastandard.

YoumayaddapassageofuptofivewordsasaFront-CoverText,andapassageofupto25wordsasaBack-CoverText,totheendofthelistofCoverTextsintheModifiedVersion.OnlyonepassageofFront-CoverTextandoneofBack-CoverTextmaybeaddedby(orthrougharrangementsmadeby)anyoneentity.IftheDocumentalreadyincludesacovertextforthesamecover,previouslyaddedbyyouorbyarrangementmadebythesameentityyouareactingonbehalfof,youmaynotaddanother;butyoumayreplacetheoldone,onexplicitpermissionfromthepreviouspublisherthataddedtheoldone.

Theauthor(s)andpublisher(s)oftheDocumentdonotbythisLicensegivepermissiontousetheirnamesforpublicityforortoassertorimplyendorsementofanyModifiedVersion.

<<Copyinginquantity 123456789101112 Combiningdocuments>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>GNUFreeDocumentationLicense>Combiningdocuments <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

G.5.CombiningdocumentsYoumaycombinetheDocumentwithotherdocumentsreleasedunderthisLicense,underthetermsdefinedinsection4aboveformodifiedversions,providedthatyouincludeinthecombinationalloftheInvariantSectionsofalloftheoriginaldocuments,unmodified,andlistthemallasInvariantSectionsofyourcombinedworkinitslicensenotice.

ThecombinedworkneedonlycontainonecopyofthisLicense,andmultipleidenticalInvariantSectionsmaybereplacedwithasinglecopy.IftherearemultipleInvariantSectionswiththesamenamebutdifferentcontents,makethetitleofeachsuchsectionuniquebyaddingattheendofit,inparentheses,thenameoftheoriginalauthororpublisherofthatsectionifknown,orelseauniquenumber.MakethesameadjustmenttothesectiontitlesinthelistofInvariantSectionsinthelicensenoticeofthecombinedwork.

Inthecombination,youmustcombineanysectionsentitled"History"inthevariousoriginaldocuments,formingonesectionentitled"History";likewisecombineanysectionsentitled"Acknowledgements",andanysectionsentitled"Dedications".Youmustdeleteallsectionsentitled"Endorsements."

<<Modifications 123456789101112

Collectionsofdocuments>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>GNUFreeDocumentationLicense>Collectionsofdocuments <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

G.6.CollectionsofdocumentsYoumaymakeacollectionconsistingoftheDocumentandotherdocumentsreleasedunderthisLicense,andreplacetheindividualcopiesofthisLicenseinthevariousdocumentswithasinglecopythatisincludedinthecollection,providedthatyoufollowtherulesofthisLicenseforverbatimcopyingofeachofthedocumentsinallotherrespects.

Youmayextractasingledocumentfromsuchacollection,anddistributeitindividuallyunderthisLicense,providedyouinsertacopyofthisLicenseintotheextracteddocument,andfollowthisLicenseinallotherrespectsregardingverbatimcopyingofthatdocument.

<<Combiningdocuments 123456789101112

Aggregationwithindependentworks>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>GNUFreeDocumentationLicense>Aggregationwithindependentworks <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

G.7.AggregationwithindependentworksAcompilationoftheDocumentoritsderivativeswithotherseparateandindependentdocumentsorworks,inoronavolumeofastorageordistributionmedium,doesnotasawholecountasaModifiedVersionoftheDocument,providednocompilationcopyrightisclaimedforthecompilation.Suchacompilationiscalledan"aggregate",andthisLicensedoesnotapplytotheotherself-containedworksthuscompiledwiththeDocument,onaccountoftheirbeingthuscompiled,iftheyarenotthemselvesderivativeworksoftheDocument.

IftheCoverTextrequirementofsection3isapplicabletothesecopiesoftheDocument,theniftheDocumentislessthanonequarteroftheentireaggregate,theDocument'sCoverTextsmaybeplacedoncoversthatsurroundonlytheDocumentwithintheaggregate.Otherwisetheymustappearoncoversaroundthewholeaggregate.

<<Collectionsofdocuments 1234567891011

12 Translation>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>GNUFreeDocumentationLicense>Translation <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

G.8.TranslationTranslationisconsideredakindofmodification,soyoumaydistributetranslationsoftheDocumentunderthetermsofsection4.ReplacingInvariantSectionswithtranslationsrequiresspecialpermissionfromtheircopyrightholders,butyoumayincludetranslationsofsomeorallInvariantSectionsinadditiontotheoriginalversionsoftheseInvariantSections.YoumayincludeatranslationofthisLicenseprovidedthatyoualsoincludetheoriginalEnglishversionofthisLicense.IncaseofadisagreementbetweenthetranslationandtheoriginalEnglishversionofthisLicense,theoriginalEnglishversionwillprevail.

<<Aggregationwithindependentworks 1234567891011

12 Termination>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>GNUFreeDocumentationLicense>Termination <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

G.9.TerminationYoumaynotcopy,modify,sublicense,ordistributetheDocumentexceptasexpresslyprovidedforunderthisLicense.Anyotherattempttocopy,modify,sublicenseordistributetheDocumentisvoid,andwillautomaticallyterminateyourrightsunderthisLicense.However,partieswhohavereceivedcopies,orrights,fromyouunderthisLicensewillnothavetheirlicensesterminatedsolongassuchpartiesremaininfullcompliance.

<<Translation 123456789101112

Futurerevisionsofthislicense>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>GNUFreeDocumentationLicense>Futurerevisionsofthislicense <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

G.10.FuturerevisionsofthislicenseTheFreeSoftwareFoundationmaypublishnew,revisedversionsoftheGNUFreeDocumentationLicensefromtimetotime.Suchnewversionswillbesimilarinspirittothepresentversion,butmaydifferindetailtoaddressnewproblemsorconcerns.Seehttp://www.gnu.org/copyleft/.

EachversionoftheLicenseisgivenadistinguishingversionnumber.IftheDocumentspecifiesthataparticularnumberedversionofthisLicense"oranylaterversion"appliestoit,youhavetheoptionoffollowingthetermsandconditionseitherofthatspecifiedversionorofanylaterversionthathasbeenpublished(notasadraft)bytheFreeSoftwareFoundation.IftheDocumentdoesnotspecifyaversionnumberofthisLicense,youmaychooseanyversioneverpublished(notasadraft)bytheFreeSoftwareFoundation.

<<Termination 123456789101112

HowtousethisLicenseforyourdocuments>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>GNUFreeDocumentationLicense>HowtousethisLicenseforyourdocuments <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

G.11.HowtousethisLicenseforyourdocumentsTousethisLicenseinadocumentyouhavewritten,includeacopyoftheLicenseinthedocumentandputthefollowingcopyrightandlicensenoticesjustafterthetitlepage:

Copyright(c)YEARYOURNAME.Permissionisgrantedtocopy,distributeand/ormodifythisdocumentunderthetermsoftheGNUFreeDocumentationLicense,Version1.1oranylaterversionpublishedbytheFreeSoftwareFoundation;withtheInvariantSectionsbeingLISTTHEIRTITLES,withtheFront-CoverTextsbeingLIST,andwiththeBack-CoverTextsbeingLIST.Acopyofthelicenseisincludedinthesectionentitled"GNUFreeDocumentationLicense".

IfyouhavenoInvariantSections,write"withnoInvariantSections"insteadofsayingwhichonesareinvariant.IfyouhavenoFront-CoverTexts,write"noFront-CoverTexts"insteadof"Front-CoverTextsbeingLIST";likewiseforBack-CoverTexts.

Ifyourdocumentcontainsnontrivialexamplesofprogramcode,werecommendreleasingtheseexamplesinparallelunderyourchoiceoffreesoftwarelicense,suchastheGNUGeneralPublicLicense,topermittheiruseinfreesoftware.

<<Futurerevisionsofthislicense 1234567891011

12 Pythonlicense>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>Pythonlicense <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

H.PythonlicenseH.A.HistoryofthesoftwareH.B.TermsandconditionsforaccessingorotherwiseusingPython

H.B.1.PSFlicenseagreementH.B.2.BeOpenPythonopensourcelicenseagreementversion1H.B.3.CNRIopensourceGPL-compatiblelicenseagreementH.B.4.CWIpermissionsstatementanddisclaimer

H.A.HistoryofthesoftwarePythonwascreatedintheearly1990sbyGuidovanRossumatStichtingMathematischCentrum(CWI)intheNetherlandsasasuccessorofalanguagecalledABC.GuidoisPython'sprincipalauthor,althoughitincludesmanycontributionsfromothers.ThelastversionreleasedfromCWIwasPython1.2.In1995,GuidocontinuedhisworkonPythonattheCorporationforNationalResearchInitiatives(CNRI)inReston,Virginiawherehereleasedseveralversionsofthesoftware.Python1.6wasthelastoftheversionsreleasedbyCNRI.In2000,GuidoandthePythoncoredevelopmentteammovedtoBeOpen.comtoformtheBeOpenPythonLabsteam.Python2.0wasthefirstandonlyreleasefromBeOpen.com.

FollowingthereleaseofPython1.6,andafterGuidovanRossumleftCNRItoworkwithcommercialsoftwaredevelopers,itbecameclearthattheabilitytousePythonwithsoftwareavailableundertheGNUPublicLicense(GPL)wasverydesirable.CNRIandtheFreeSoftwareFoundation(FSF)interactedtodevelopenablingwordingchangestothePythonlicense.Python1.6.1isessentiallythesameasPython1.6,withafewminorbugfixes,andwithadifferentlicensethatenableslaterversionstobeGPL-compatible.Python2.1isaderivativeworkofPython1.6.1,aswellasofPython2.0.

AfterPython2.0wasreleasedbyBeOpen.com,GuidovanRossumandtheotherPythonLabsdevelopersjoinedDigitalCreations.Allintellectualpropertyaddedfromthispointon,startingwithPython2.1anditsalphaandbetareleases,isownedbythePythonSoftwareFoundation(PSF),anon-profitmodeledaftertheApacheSoftwareFoundation.Seehttp://www.python.org/psf/formoreinformationaboutthePSF.

ThankstothemanyoutsidevolunteerswhohaveworkedunderGuido'sdirectiontomakethesereleasespossible.

<<HowtousethisLicenseforyourdocuments 12

Termsandconditionsforaccessingorotherwise

usingPython>>

©2000,2001,2002,2003,2004 MarkPilgrim

: �?/a>>DiveIntoPython>Pythonlicense>TermsandconditionsforaccessingorotherwiseusingPython <<

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

H.B.TermsandconditionsforaccessingorotherwiseusingPython

H.B.1.PSFlicenseagreementH.B.2.BeOpenPythonopensourcelicenseagreementversion1H.B.3.CNRIopensourceGPL-compatiblelicenseagreementH.B.4.CWIpermissionsstatementanddisclaimer

H.B.1.PSFlicenseagreement

1. ThisLICENSEAGREEMENTisbetweenthePythonSoftwareFoundation("PSF"),andtheIndividualorOrganization("Licensee")accessingandotherwiseusingPython2.1.1softwareinsourceorbinaryformanditsassociateddocumentation.

2. SubjecttothetermsandconditionsofthisLicenseAgreement,PSFherebygrantsLicenseeanonexclusive,royalty-free,world-widelicensetoreproduce,analyze,test,performand/ordisplaypublicly,preparederivativeworks,distribute,andotherwiseusePython2.1.1aloneorinanyderivativeversion,provided,however,thatPSF'sLicenseAgreementandPSF'snoticeofcopyright,i.e.,"Copyright(c)2001PythonSoftwareFoundation;AllRightsReserved"areretainedinPython2.1.1aloneorinanyderivativeversionpreparedbyLicensee.

3. IntheeventLicenseepreparesaderivativeworkthatisbasedonorincorporatesPython2.1.1oranypartthereof,andwantstomakethederivativeworkavailabletoothersasprovidedherein,thenLicenseeherebyagreestoincludeinanysuchworkabriefsummaryofthechangesmadetoPython2.1.1.

4. PSFismakingPython2.1.1availabletoLicenseeonan"ASIS"basis.PSFMAKESNOREPRESENTATIONSORWARRANTIES,EXPRESSORIMPLIED.BYWAYOFEXAMPLE,BUTNOTLIMITATION,PSF

MAKESNOANDDISCLAIMSANYREPRESENTATIONORWARRANTYOFMERCHANTABILITYORFITNESSFORANYPARTICULARPURPOSEORTHATTHEUSEOFPYTHON2.1.1WILLNOTINFRINGEANYTHIRDPARTYRIGHTS.

5. PSFSHALLNOTBELIABLETOLICENSEEORANYOTHERUSERSOFPYTHON2.1.1FORANYINCIDENTAL,SPECIAL,ORCONSEQUENTIALDAMAGESORLOSSASARESULTOFMODIFYING,DISTRIBUTING,OROTHERWISEUSINGPYTHON2.1.1,ORANYDERIVATIVETHEREOF,EVENIFADVISEDOFTHEPOSSIBILITYTHEREOF.

6. ThisLicenseAgreementwillautomaticallyterminateuponamaterialbreachofitstermsandconditions.

7. NothinginthisLicenseAgreementshallbedeemedtocreateanyrelationshipofagency,partnership,orjointventurebetweenPSFandLicensee.ThisLicenseAgreementdoesnotgrantpermissiontousePSFtrademarksortradenameinatrademarksensetoendorseorpromoteproductsorservicesofLicensee,oranythirdparty.

8. Bycopying,installingorotherwiseusingPython2.1.1,LicenseeagreestobeboundbythetermsandconditionsofthisLicenseAgreement.

H.B.2.BeOpenPythonopensourcelicenseagreementversion1

1. ThisLICENSEAGREEMENTisbetweenBeOpen.com("BeOpen"),havinganofficeat160SaratogaAvenue,SantaClara,CA95051,andtheIndividualorOrganization("Licensee")accessingandotherwiseusingthissoftwareinsourceorbinaryformanditsassociateddocumentation("theSoftware").

2. SubjecttothetermsandconditionsofthisBeOpenPythonLicenseAgreement,BeOpenherebygrantsLicenseeanon-exclusive,royalty-free,world-widelicensetoreproduce,analyze,test,performand/ordisplaypublicly,preparederivativeworks,distribute,andotherwiseusethe

Softwarealoneorinanyderivativeversion,provided,however,thattheBeOpenPythonLicenseisretainedintheSoftware,aloneorinanyderivativeversionpreparedbyLicensee.

3. BeOpenismakingtheSoftwareavailabletoLicenseeonan"ASIS"basis.BEOPENMAKESNOREPRESENTATIONSORWARRANTIES,EXPRESSORIMPLIED.BYWAYOFEXAMPLE,BUTNOTLIMITATION,BEOPENMAKESNOANDDISCLAIMSANYREPRESENTATIONORWARRANTYOFMERCHANTABILITYORFITNESSFORANYPARTICULARPURPOSEORTHATTHEUSEOFTHESOFTWAREWILLNOTINFRINGEANYTHIRDPARTYRIGHTS.

4. BEOPENSHALLNOTBELIABLETOLICENSEEORANYOTHERUSERSOFTHESOFTWAREFORANYINCIDENTAL,SPECIAL,ORCONSEQUENTIALDAMAGESORLOSSASARESULTOFUSING,MODIFYINGORDISTRIBUTINGTHESOFTWARE,ORANYDERIVATIVETHEREOF,EVENIFADVISEDOFTHEPOSSIBILITYTHEREOF.

5. ThisLicenseAgreementwillautomaticallyterminateuponamaterialbreachofitstermsandconditions.

6. ThisLicenseAgreementshallbegovernedbyandinterpretedinallrespectsbythelawoftheStateofCalifornia,excludingconflictoflawprovisions.NothinginthisLicenseAgreementshallbedeemedtocreateanyrelationshipofagency,partnership,orjointventurebetweenBeOpenandLicensee.ThisLicenseAgreementdoesnotgrantpermissiontouseBeOpentrademarksortradenamesinatrademarksensetoendorseorpromoteproductsorservicesofLicensee,oranythirdparty.Asanexception,the"BeOpenPython"logosavailableathttp://www.pythonlabs.com/logos.htmlmaybeusedaccordingtothepermissionsgrantedonthatwebpage.

7. Bycopying,installingorotherwiseusingthesoftware,LicenseeagreestobeboundbythetermsandconditionsofthisLicenseAgreement.

H.B.3.CNRIopensourceGPL-compatiblelicenseagreement

1. ThisLICENSEAGREEMENTisbetweentheCorporationforNationalResearchInitiatives,havinganofficeat1895PrestonWhiteDrive,Reston,VA20191("CNRI"),andtheIndividualorOrganization("Licensee")accessingandotherwiseusingPython1.6.1softwareinsourceorbinaryformanditsassociateddocumentation.

2. SubjecttothetermsandconditionsofthisLicenseAgreement,CNRIherebygrantsLicenseeanonexclusive,royalty-free,world-widelicensetoreproduce,analyze,test,performand/ordisplaypublicly,preparederivativeworks,distribute,andotherwiseusePython1.6.1aloneorinanyderivativeversion,provided,however,thatCNRI'sLicenseAgreementandCNRI'snoticeofcopyright,i.e.,"Copyright(c)1995-2001CorporationforNationalResearchInitiatives;AllRightsReserved"areretainedinPython1.6.1aloneorinanyderivativeversionpreparedbyLicensee.Alternately,inlieuofCNRI'sLicenseAgreement,Licenseemaysubstitutethefollowingtext(omittingthequotes):"Python1.6.1ismadeavailablesubjecttothetermsandconditionsinCNRI'sLicenseAgreement.ThisAgreementtogetherwithPython1.6.1maybelocatedontheInternetusingthefollowingunique,persistentidentifier(knownasahandle):1895.22/1013.ThisAgreementmayalsobeobtainedfromaproxyserverontheInternetusingthefollowingURL:http://hdl.handle.net/1895.22/1013".

3. IntheeventLicenseepreparesaderivativeworkthatisbasedonorincorporatesPython1.6.1oranypartthereof,andwantstomakethederivativeworkavailabletoothersasprovidedherein,thenLicenseeherebyagreestoincludeinanysuchworkabriefsummaryofthechangesmadetoPython1.6.1.

4. CNRIismakingPython1.6.1availabletoLicenseeonan"ASIS"basis.CNRIMAKESNOREPRESENTATIONSORWARRANTIES,EXPRESSORIMPLIED.BYWAYOFEXAMPLE,BUTNOTLIMITATION,CNRIMAKESNOANDDISCLAIMSANYREPRESENTATIONOR

WARRANTYOFMERCHANTABILITYORFITNESSFORANYPARTICULARPURPOSEORTHATTHEUSEOFPYTHON1.6.1WILLNOTINFRINGEANYTHIRDPARTYRIGHTS.

5. CNRISHALLNOTBELIABLETOLICENSEEORANYOTHERUSERSOFPYTHON1.6.1FORANYINCIDENTAL,SPECIAL,ORCONSEQUENTIALDAMAGESORLOSSASARESULTOFMODIFYING,DISTRIBUTING,OROTHERWISEUSINGPYTHON1.6.1,ORANYDERIVATIVETHEREOF,EVENIFADVISEDOFTHEPOSSIBILITYTHEREOF.

6. ThisLicenseAgreementwillautomaticallyterminateuponamaterialbreachofitstermsandconditions.

7. ThisLicenseAgreementshallbegovernedbythefederalintellectualpropertylawoftheUnitedStates,includingwithoutlimitationthefederalcopyrightlaw,and,totheextentsuchU.S.federallawdoesnotapply,bythelawoftheCommonwealthofVirginia,excludingVirginia'sconflictoflawprovisions.Notwithstandingtheforegoing,withregardtoderivativeworksbasedonPython1.6.1thatincorporatenon-separablematerialthatwaspreviouslydistributedundertheGNUGeneralPublicLicense(GPL),thelawoftheCommonwealthofVirginiashallgovernthisLicenseAgreementonlyastoissuesarisingunderorwithrespecttoParagraphs4,5,and7ofthisLicenseAgreement.NothinginthisLicenseAgreementshallbedeemedtocreateanyrelationshipofagency,partnership,orjointventurebetweenCNRIandLicensee.ThisLicenseAgreementdoesnotgrantpermissiontouseCNRItrademarksortradenameinatrademarksensetoendorseorpromoteproductsorservicesofLicensee,oranythirdparty.

8. Byclickingonthe"ACCEPT"buttonwhereindicated,orbycopying,installingorotherwiseusingPython1.6.1,LicenseeagreestobeboundbythetermsandconditionsofthisLicenseAgreement.

H.B.4.CWIpermissionsstatementanddisclaimer

Copyright(c)1991-1995,StichtingMathematischCentrumAmsterdam,TheNetherlands.Allrightsreserved.

Permissiontouse,copy,modify,anddistributethissoftwareanditsdocumentationforanypurposeandwithoutfeeisherebygranted,providedthattheabovecopyrightnoticeappearinallcopiesandthatboththatcopyrightnoticeandthispermissionnoticeappearinsupportingdocumentation,andthatthenameofStichtingMathematischCentrumorCWInotbeusedinadvertisingorpublicitypertainingtodistributionofthesoftwarewithoutspecific,writtenpriorpermission.

STICHTINGMATHEMATISCHCENTRUMDISCLAIMSALLWARRANTIESWITHREGARDTOTHISSOFTWARE,INCLUDINGALLIMPLIEDWARRANTIESOFMERCHANTABILITYANDFITNESS,INNOEVENTSHALLSTICHTINGMATHEMATISCHCENTRUMBELIABLEFORANYSPECIAL,INDIRECTORCONSEQUENTIALDAMAGESORANYDAMAGESWHATSOEVERRESULTINGFROMLOSSOFUSE,DATAORPROFITS,WHETHERINANACTIONOFCONTRACT,NEGLIGENCEOROTHERTORTIOUSACTION,ARISINGOUTOFORINCONNECTIONWITHTHEUSEORPERFORMANCEOFTHISSOFTWARE.

<<Pythonlicense 12

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython >>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

DiveIntoPython2004520

200512—20064(update-060425)

©2000,2001,2002,2003,2004 MarkPilgrim

http://diveintopython.org/

GNU(GNUFreeDocumentationLicense1.1)/ G,GNUFreeDocumentationLicense

Python( Python)/ H,Pythonlicense

Zoom.Quiet SVN WIKI http://www.djangocn.org/BLOG

/CPUG obp

limodou(limodouATgmailDOTcom)Zoom.Quiet(zoom.quietATgmailDOTcom)JasonXie(jasonATsinoeslDOTorg)YuLin(yulin724ATgmailDOTcom)WeigangLI(dimensATgmailDOTcom)wolfg(wolfg1969ATgmailDOTcom)Osmond(sinosmondATgmailDOTcom)

WIKI

GFDL

1.Python1.1.Python1.2.WindowsPython1.3.MacOSXPython1.4.MacOS9Python1.5.RedHatLinuxPython1.6.DebianGNU/LinuxPython1.7.Python1.8.PythonShell1.9.

2.Python2.1.2.2.

2.2.1.Python2.3.2.4.

2.4.1.2.4.2.

2.5.2.6.

3.3.1.Dictionary

3.1.1.Dictionary3.1.2.Dictionary3.1.3.dictionary

3.2.List3.2.1.List3.2.2.list3.2.3.list3.2.4.list3.2.5.list

3.3.Tuple3.4.

3.4.1.3.4.2.

3.5.3.6.list3.7.list

3.7.1.3.8.

4.4.1.4.2.4.3.typestrdir

4.3.1.type4.3.2.str4.3.3.

4.4.getattr4.4.1.getattr4.4.2.getattr

4.5.4.6.andor

4.6.1.and-or4.7.lambda

4.7.1.lambda4.8.4.9.

5.5.1.5.2.frommoduleimport5.3.

5.3.1.5.3.2.self__init__

5.4.5.4.1.

5.5.UserDict:5.6.

5.6.1.5.7.5.8.5.9.5.10.

6.6.1.

6.1.1.6.2.

6.2.1.6.2.2.6.2.3.I/O6.2.4.

6.3.for6.4.sys.modules6.5.Directory6.6.6.7.

7.7.1.7.2.7.3.

7.3.1.7.3.2.

7.4.{n,m}7.4.1.

7.5.7.6.:7.7.

8.HTML8.1.8.2.sgmllib.py8.3.HTML8.4.BaseHTMLProcessor.py8.5.localsglobals8.6.dictionary8.7.8.8.dialect.py8.9.8.10.

9.XML9.1.9.2.9.3.XML9.4.Unicode9.5.9.6.9.7.Segue

10.ScriptsStreams10.1.10.2.10.3.10.4.10.5.Creatingseparatehandlersbynodetype10.6.10.7.10.8.

11.HTTPWeb11.1.11.2.HTTP11.3.HTTP

11.3.1.(User-Agent)11.3.2.(Redirects)11.3.3.Last-Modified/If-Modified-Since11.3.4.ETag/If-None-Match11.3.5.(Compression)

11.4.HTTPweb11.5.User-Agent11.6.Last-ModifiedETag11.7.11.8.11.9.11.10.

12.SOAPWeb12.1.12.2.SOAP

12.2.1.PyXML12.2.2.fpconst12.2.3.SOAPpy

12.3.SOAP12.4.SOAP12.5.WSDL12.6.WSDLSOAP12.7.Google12.8.SOAP12.9.

13.13.1.II13.2.13.3.romantest.py13.4.Testingforsuccess13.5.Testingforfailure13.6.Testingforsanity

14.14.1.roman.py,114.2.roman.py,214.3.roman.py,314.4.roman.py,414.5.roman.py,5

15.15.1.bugs15.2.15.3.15.4.15.5.

16.FunctionalProgramming16.1.16.2.16.3.16.4.16.5.16.6.16.7.16.8.

17.17.1.17.2.plural.py,117.3.plural.py,217.4.plural.py,317.5.plural.py,417.6.plural.py,517.7.plural.py,617.8.

18.18.1.18.2.timeit18.3.18.4.18.5.18.6.18.7.

A.B.C.D.E.F.G.GNUFreeDocumentationLicense

G.0.PreambleG.1.ApplicabilityanddefinitionsG.2.VerbatimcopyingG.3.CopyinginquantityG.4.ModificationsG.5.CombiningdocumentsG.6.CollectionsofdocumentsG.7.AggregationwithindependentworksG.8.TranslationG.9.TerminationG.10.FuturerevisionsofthislicenseG.11.HowtousethisLicenseforyourdocuments

H.PythonlicenseH.A.HistoryofthesoftwareH.B.TermsandconditionsforaccessingorotherwiseusingPython

H.B.1.PSFlicenseagreementH.B.2.BeOpenPythonopensourcelicenseagreementversion1H.B.3.CNRIopensourceGPL-compatiblelicenseagreementH.B.4.CWIpermissionsstatementanddisclaimer

Python>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>Python <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

1 Python1.1.Python1.2.WindowsPython1.3.MacOSXPython1.4.MacOS9Python1.5.RedHatLinuxPython1.6.DebianGNU/LinuxPython1.7.Python1.8.PythonShell1.9.

Python,, Python

1.1. Python Python,

,ISP PythonLinux PythonMac, MacOSX10.2 Python

Windows Python,Windows Python

, PythonWindows, MacOS,MacOSX, UNIX——LinuxSunSolaris,AS/400,Amiga,OS/2,BeOS,

Python Python, ,Windows Python,Linux

,“ Python ”,

<<DiveIntoPython 123456789 WindowsPython>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>Python <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

2 Python2.1.2.2.

2.2.1.Python2.3.2.4.

2.4.1.2.4.2.

2.5.2.6.

,,

2.1., Python

,,

2.1.odbchelper.py

,

defbuildConnectionString(params):

"""Buildaconnectionstringfromadictionaryofparameters.

Returnsstring."""

return";".join(["%s=%s"%(k,v)fork,vinparams.items()])

if__name__=="__main__":

myParams={"server":"mpilgrim",\

"database":"master",\

"uid":"sa",\

"pwd":"secret"\

}

printbuildConnectionString(myParams)

,

Windows ActivePythonIDE, File->Run...(Ctrl-R)Python

MacOS PythonIDE, Python->Runwindow...(Cmd-R) Python, IDE .py,,, Runas

__main__ ,

UNIX( MacOSX), pythonodbchelper.py

odbchelper.py:

server=mpilgrim;uid=sa;database=master;pwd=secret

<< 123456 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

44.1.4.2.4.3.typestrdir

4.3.1.type4.3.2.str4.3.3.

4.4.getattr4.4.1.getattr4.4.2.getattr

4.5.4.6.andor

4.6.1.and-or4.7.lambda

4.7.1.lambda4.8.4.9.

Python Python,

4.1. Python 2 Python

4.1.apihelper.py

,

definfo(object,spacing=10,collapse=1):

"""Printmethodsanddocstrings.

Takesmodule,class,list,dictionary,orstring."""

methodList=[methodformethodindir(object)ifcallable(getattr(object,method))]

processFunc=collapseand(lambdas:"".join(s.split()))or(

print"\n".join(["%s%s"%

(method.ljust(spacing),

processFunc(str(getattr(object,method).__doc__)))

formethodinmethodList])

if__name__=="__main__":

printinfo.__doc__

info objectspacing collapse

info docstring

if__name__ info docstring

if ==,

info PythonIDElist docstring

4.2.apihelper.py

>>>fromapihelperimportinfo

>>>li=[]

>>>info(li)

appendL.append(object)--appendobjecttoend

countL.count(value)->integer--returnnumberofoccurrencesofvalue

extendL.extend(list)--extendlistbyappendinglistelements

indexL.index(value)->integer--returnindexoffirstoccurrenceofvalue

insertL.insert(index,object)--insertobjectbeforeindex

popL.pop([index])->item--removeandreturnitematindex(defaultlast)

removeL.remove(value)--removefirstoccurrenceofvalue

reverseL.reverse()--reverse*INPLACE*

sortL.sort([cmpfunc])--sort*INPLACE*;ifgiven,cmpfunc(x,y)->-1,0,1

docstring collapse 010 spacing

4.3.apihelper.py

>>>importodbchelper

>>>info(odbchelper)

buildConnectionStringBuildaconnectionstringfromadictionaryReturnsstring.

>>>info(odbchelper,30)

buildConnectionStringBuildaconnectionstringfromadictionaryReturnsstring.

>>>info(odbchelper,30,0)

buildConnectionStringBuildaconnectionstringfromadictionary

Returnsstring.

<< 123456789 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

33.1.Dictionary

3.1.1.Dictionary3.1.2.Dictionary3.1.3.dictionary

3.2.List3.2.1.List3.2.2.list3.2.3.list3.2.4.list3.2.5.list

3.3.Tuple3.4.

3.4.1.3.4.2.

3.5.3.6.list3.7.list

3.7.1.3.8.

Python,,dictionary()tuple()list()(,) Perlhacker,dictionarylist,tuple

3.1.Dictionary3.1.1.Dictionary3.1.2.Dictionary3.1.3.dictionary

Dictionary Python,

Pythondictionary Perlhash() Perl, Python,, Python

Pythondictionary Java Hashtable

Pythondictionary VisualBasicScripting.Dictionary

3.1.1.Dictionary

3.1.Dictionary

>>>d={"server":"mpilgrim","database":"master"}

>>>d

{'server':'mpilgrim','database':'master'}

>>>d["server"]

'mpilgrim'

>>>d["database"]

'master'

>>>d["mpilgrim"]

Traceback(innermostlast):

File"<interactiveinput>",line1,in?

KeyError:mpilgrim

dictionary,, dkey-value,

'server'key, d["server"], 'mpilgrim'

'database'key, d["database"], 'master'

key,key d["server"] 'mpilgrim',d["mpilgrim"], 'mpilgrim'key

3.1.2.Dictionary

3.2.Dictionary

>>>d

{'server':'mpilgrim','database':'master'}

>>>d["database"]="pubs"

>>>d

{'server':'mpilgrim','database':'pubs'}

>>>d["uid"]="sa"

>>>d

{'server':'mpilgrim','uid':'sa','database':'pubs'}

dictionarykeykeykey-value(,,,,key)

(key 'uid',value 'sa'),

Dictionary“ ”,,,(key)dictionary,dictionary

dictionary,:dictionarykey

3.3.Dictionarykey

>>>d={}

>>>d["key"]="value"

>>>d["key"]="othervalue"

>>>d

{'key':'othervalue'}

>>>d["Key"]="thirdvalue"

>>>d

{'Key':'thirdvalue','key':'othervalue'}

dictionary key,dictionary key, Python, dictionarykey-value, Python

3.4.dictionary

>>>d

{'server':'mpilgrim','uid':'sa','database':'pubs'}

>>>d["retrycount"]=3

>>>d

{'server':'mpilgrim','uid':'sa','database':'master','retrycount':3}

>>>d[42]="douglas"

>>>d

{'server':'mpilgrim','uid':'sa','database':'master',

42:'douglas','retrycount':3}

DictionaryDictionary,,,,dictionarydictionary,dictionary,Dictionarykey,,()dictionarykey

3.1.3.dictionary

3.5.dictionary

>>>d

{'server':'mpilgrim','uid':'sa','database':'master',

42:'douglas','retrycount':3}

>>>deld[42]

>>>d

{'server':'mpilgrim','uid':'sa','database':'master','retrycount':3}

>>>d.clear()

>>>d

{}

delkeydictionarycleardictionarydictionary

HowtoThinkLikeaComputerScientistdictionary dictionary

PythonKnowledgeBase dictionaryPythonCookbook keydictionaryPythonLibraryReference dictionary

<< 12345678 List>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

55.1.5.2.frommoduleimport5.3.

5.3.1.5.3.2.self__init__

5.4.5.4.1.

5.5.UserDict:5.6.

5.6.1.5.7.5.8.5.9.5.10.

Python

5.1. Python docstrings

5.1.fileinfo.py

,

"""Frameworkforgettingfiletype-specificmetadata.

Instantiateappropriateclasswithfilename.Returnedobjectactslikea

dictionary,withkey-valuepairsforeachpieceofmetadata.

importfileinfo

info=fileinfo.MP3FileInfo("/music/ap/mahadeva.mp3")

print"\\n".join(["%s=%s"%(k,v)fork,vininfo.items()])

OruselistDirectoryfunctiontogetinfoonallfilesinadirectory.

forinfoinfileinfo.listDirectory("/music/ap/",[".mp3"]):

...

Frameworkcanbeextendedbyaddingclassesforparticularfiletypes,e.g.

HTMLFileInfo,MPGFileInfo,DOCFileInfo.Eachclassiscompletelyresponsiblefor

parsingitsfilesappropriately;seeMP3FileInfoforexample.

"""

importos

importsys

fromUserDictimportUserDict

defstripnulls(data):

"stripwhitespaceandnulls"

returndata.replace("\00","").strip()

classFileInfo(UserDict):

"storefilemetadata"

def__init__(self,filename=None):

UserDict.__init__(self)

self["name"]=filename

classMP3FileInfo(FileInfo):

"storeID3v1.0MP3tags"

tagDataMap={"title":(3,33,stripnulls),

"artist":(33,63,stripnulls),

"album":(63,93,stripnulls),

"year":(93,97,stripnulls),

"comment":(97,126,stripnulls),

"genre":(127,128,ord)}

def__parse(self,filename):

"parseID3v1.0tagsfromMP3file"

self.clear()

try:

fsock=open(filename,"rb",0)

try:

fsock.seek(-128,2)

tagdata=fsock.read(128)

finally:

fsock.close()

iftagdata[:3]=="TAG":

fortag,(start,end,parseFunc)inself.tagDataMap.items():

self[tag]=parseFunc(tagdata[start:end])

exceptIOError:

pass

def__setitem__(self,key,item):

ifkey=="name"anditem:

self.__parse(item)

FileInfo.__setitem__(self,key,item)

deflistDirectory(directory,fileExtList):

"getlistoffileinfoobjectsforfilesofparticularextensions"

fileList=[os.path.normcase(f)

forfinos.listdir(directory)]

fileList=[os.path.join(directory,f)

forfinfileList

ifos.path.splitext(f)[1]infileExtList]

defgetFileInfoClass(filename,module=sys.modules[FileInfo.__module__]):

"getfileinfoclassfromfilenameextension"

subclass="%sFileInfo"%os.path.splitext(filename)[1].upper()[1:]

returnhasattr(module,subclass)andgetattr(module,subclass)

return[getFileInfoClass(f)(f)forfinfileList]

if__name__=="__main__":

forinfoinlistDirectory("/music/_singles/",[".mp3"]):

print"\n".join(["%s=%s"%(k,v)fork,vininfo.items()])

print

MP3

album=

artist=GhostintheMachine

title=ATimeLongForgotten(Concept

genre=31

name=/music/_singles/a_time_long_forgotten_con.mp3

year=1999

comment=http://mp3.com/ghostmachine

album=RaveMix

artist=***DJMARY-JANE***

title=HELLRAISER****TrancefromHell

genre=31

name=/music/_singles/hellraiser.mp3

year=2000

comment=http://mp3.com/DJMARYJANE

album=RaveMix

artist=***DJMARY-JANE***

title=KAIRO****THEBESTGOA

genre=31

name=/music/_singles/kairo.mp3

year=2000

comment=http://mp3.com/DJMARYJANE

album=Journeys

artist=MastersofBalance

title=LongWayHome

genre=31

name=/music/_singles/long_way_home1.mp3

year=2000

comment=http://mp3.com/MastersofBalan

album=

artist=TheCynicProject

title=Sidewinder

genre=18

name=/music/_singles/sidewinder.mp3

year=2000

comment=http://mp3.com/cynicproject

album=Digitosis@128k

artist=VXpanded

title=Spinning

genre=255

name=/music/_singles/spinning.mp3

year=2000

comment=http://mp3.com/artists/95/vxp

<< 12345678910 frommoduleimport>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

66.1.

6.1.1.6.2.

6.2.1.6.2.2.6.2.3.I/O6.2.4.

6.3.for6.4.sys.modules6.5.Directory6.6.6.7.

,,, for, os sys, Python

6.1.6.1.1.

Python try...except

Python try...except raise Java C++try...catch throw

Python Python Python

KeyError ValueError AttributeError NameError TypeError

PythonIDE IDE Python IDE Python

bug

6.1.

>>>fsock=open("/notthere","r")

Traceback(innermostlast):

File"<interactiveinput>",line1,in?

IOError:[Errno2]Nosuchfileordirectory:'/notthere'

>>>try:

...fsock=open("/notthere")

...exceptIOError:

...print"Thefiledoesnotexist,exitinggracefully"

...print"Thislinewillalwaysprint"

Thefiledoesnotexist,exitinggracefully

Thislinewillalwaysprint

open open IOError IOErrorPython

try...except open IOError exceptIOError: try...except

6.1.1.

Python ImportError

Exception, raise

getpass, UNIX,Windows

6.2.

#Bindthenamegetpasstotheappropriatefunction

try:

importtermios,TERMIOS

exceptImportError:

try:

importmsvcrt

exceptImportError:

try:

fromEasyDialogsimportAskPassword

exceptImportError:

getpass=default_getpass

else:

getpass=AskPassword

else:

getpass=win_getpass

else:

getpass=unix_getpass

termios UNIX PythonImportErrorOK, termios msvcrtWindowsMicrosoft VisualC++API Python ImportError EasyDialogs MacOS PythonImportError Python getpassdefault_getpass getpass getpass getpass getpass

getpass getpass getpass

try...except else if tryelse fromEasyDialogsimportAskPassword getpassAskPassword try...except else importgetpass

PythonTutorial ,PythonLibraryReferencePythonLibraryReference getpassPythonLibraryReference traceback,PythonReferenceManual try...except

<< 1234567 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>SOAPWeb <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

12SOAPWeb12.1.12.2.SOAP

12.2.1.PyXML12.2.2.fpconst12.2.3.SOAPpy

12.3.SOAP12.4.SOAP12.5.WSDL12.6.WSDLSOAP12.7.Google12.8.SOAP12.9.

11 HTTPweb“ ” URL,“”XML

SOAPweb SOAPHTTPXML Python SOAP Python SOAPXML

SOAP SOAP SOAPWeb SOAP“ RPC-style”SOAP——

12.1.Google,? Google?

12.1.search.py

fromSOAPpyimportWSDL

#you'llneedtoconfigurethesetwovalues;

#seehttp://www.google.com/apis/

WSDLFILE='/path/to/copy/of/GoogleSearch.wsdl'

APIKEY='YOUR_GOOGLE_API_KEY'

_server=WSDL.Proxy(WSDLFILE)

defsearch(q):

"""SearchGoogleandreturnlistof{title,link,description}"""

results=_server.doGoogleSearch(

APIKEY,q,0,10,False,"",False,"","utf-8","utf-8")

return[{"title":r.title.encode("utf-8"),

"link":r.URL.encode("utf-8"),

"description":r.snippet.encode("utf-8")}

forrinresults.resultElements]

if__name__=='__main__':

importsys

forrinsearch(sys.argv[1])[:5]:

printr['title']

printr['link']

printr['description']

print

,,,

“ python”

12.2.search.py

C:\diveintopython\common\py>pythonsearch.py"python"

<b>Python</b>ProgrammingLanguage

http://www.python.org/

Homepagefor<b>Python</b>,aninterpreted,interactive,object-oriented,

extensible<br>programminglanguage.<b>...</b><b>Python</b>

isOSICertifiedOpenSource:OSICertified.

<b>Python</b>DocumentationIndex

http://www.python.org/doc/

<b>...</b>New-styleclasses(akadescrintro).Regularexpressions.Database

API.EmailUs.<br>docs@<b>python</b>.org.(c)2004.<b>Python</b>

SoftwareFoundation.<b>Python</b>Documentation.<b>...</b>

Download<b>Python</b>Software

http://www.python.org/download/

DownloadStandard<b>Python</b>Software.<b>Python</b>2.3.3isthe

currentproduction<br>versionof<b>Python</b>.<b>...</b>

<b>Python</b>isOSICertifiedOpenSource:

Pythonline

http://www.pythonline.com/

DiveInto<b>Python</b>

http://diveintopython.org/

DiveInto<b>Python</b>.<b>Python</b>fromnovicetopro.Find:

<b>...</b>Itisalsoavailableinmultiple<br>languages.Read

DiveInto<b>Python</b>.Thisbookisstillbeingwritten.<b>...</b>

http://www.xmethods.net/ SOAPwebSOAP SOAP

<< 123456789 SOAP>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

77.1.7.2.7.3.

7.3.1.7.3.2.

7.4.{n,m}7.4.1.

7.5.7.6.:7.7.

Perlre

7.1.( index,find, count),(replace)( split), s,s.lower() s.upper()s replace split

if splitjoin

(self-documenting)

<< 1234567 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>HTML <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

8HTML8.1.8.2.sgmllib.py8.3.HTML8.4.BaseHTMLProcessor.py8.5.localsglobals8.6.dictionary8.7.8.8.dialect.py8.9.8.10.

8.1. comp.lang.python: “ HTML[||] ”“[||munge] HTML ”“ HTML[||] ”

Python BaseHTMLProcessor.py HTMLdialect.py BaseHTMLProcessor.py HTML( doc

string)

8.1.BaseHTMLProcessor.py

,

fromsgmllibimportSGMLParser

importhtmlentitydefs

classBaseHTMLProcessor(SGMLParser):

defreset(self):

#extend(calledbySGMLParser.__init__)

self.pieces=[]

SGMLParser.reset(self)

defunknown_starttag(self,tag,attrs):

#calledforeachstarttag

#attrsisalistof(attr,value)tuples

#e.g.for<preclass="screen">,tag="pre",attrs=[("class","screen")]

#Ideallywewouldliketoreconstructoriginaltagandattributes,but

#wemayendupquotingattributevaluesthatweren'tquotedinthesource

#document,orwemaychangethetypeofquotesaroundtheattributevalue

#(singletodoublequotes).

#Notethatimproperlyembeddednon-HTMLcode(likeclient-sideJavascript)

#maybeparsedincorrectlybytheancestor,causingruntimescripterrors.

#Allnon-HTMLcodemustbeenclosedinHTMLcommenttags(<!--code-->)

#toensurethatitwillpassthroughthisparserunaltered(inhandle_comment).

strattrs="".join(['%s="%s"'%(key,value)forkey,value

self.pieces.append("<%(tag)s%(strattrs)s>"%locals())

defunknown_endtag(self,tag):

#calledforeachendtag,e.g.for</pre>,tagwillbe"pre"

#Reconstructtheoriginalendtag.

self.pieces.append("</%(tag)s>"%locals())

defhandle_charref(self,ref):

#calledforeachcharacterreference,e.g.for"&#160;",refwillbe"160"

#Reconstructtheoriginalcharacterreference.

self.pieces.append("&#%(ref)s;"%locals())

defhandle_entityref(self,ref):

#calledforeachentityreference,e.g.for"&copy;",refwillbe"copy"

#Reconstructtheoriginalentityreference.

self.pieces.append("&%(ref)s"%locals())

#standardHTMLentitiesareclosedwithasemicolon;otherentitiesarenot

ifhtmlentitydefs.entitydefs.has_key(ref):

self.pieces.append(";")

defhandle_data(self,text):

#calledforeachblockofplaintext,i.e.outsideofanytagand

#notcontaininganycharacterorentityreferences

#Storetheoriginaltextverbatim.

self.pieces.append(text)

defhandle_comment(self,text):

#calledforeachHTMLcomment,e.g.<!--insertJavascriptcodehere-->

#Reconstructtheoriginalcomment.

#Itisespeciallyimportantthatthesourcedocumentencloseclient-side

#code(likeJavascript)withincommentssoitcanpassthroughthis

#processorundisturbed;seecommentsinunknown_starttagfordetails.

self.pieces.append("<!--%(text)s-->"%locals())

defhandle_pi(self,text):

#calledforeachprocessinginstruction,e.g.<?instruction>

#Reconstructoriginalprocessinginstruction.

self.pieces.append("<?%(text)s>"%locals())

defhandle_decl(self,text):

#calledfortheDOCTYPE,ifpresent,e.g.

#<!DOCTYPEhtmlPUBLIC"-//W3C//DTDHTML4.01Transitional//EN"

#"http://www.w3.org/TR/html4/loose.dtd">

#ReconstructoriginalDOCTYPE

self.pieces.append("<!%(text)s>"%locals())

defoutput(self):

"""ReturnprocessedHTMLasasinglestring"""

return"".join(self.pieces)

8.2.dialect.py

importre

fromBaseHTMLProcessorimportBaseHTMLProcessor

classDialectizer(BaseHTMLProcessor):

subs=()

defreset(self):

#extend(calledfrom__init__inancestor)

#Resetalldataattributes

self.verbatim=0

BaseHTMLProcessor.reset(self)

defstart_pre(self,attrs):

#calledforevery<pre>taginHTMLsource

#Incrementverbatimmodecount,thenhandletaglikenormal

self.verbatim+=1

self.unknown_starttag("pre",attrs)

defend_pre(self):

#calledforevery</pre>taginHTMLsource

#Decrementverbatimmodecount

self.unknown_endtag("pre")

self.verbatim-=1

defhandle_data(self,text):

#override

#calledforeveryblockoftextinHTMLsource

#Ifinverbatimmode,savetextunaltered;

#otherwiseprocessthetextwithaseriesofsubstitutions

self.pieces.append(self.verbatimandtextorself.process(text))

defprocess(self,text):

#calledfromhandle_data

#Processtextblockbyperformingseriesofregularexpression

#substitutions(actualsubstitionsaredefinedindescendant)

forfromPattern,toPatterninself.subs:

text=re.sub(fromPattern,toPattern,text)

returntext

classChefDialectizer(Dialectizer):

"""convertHTMLtoSwedishChef-speak

basedontheclassicchef.x,copyright(c)1992,1993JohnHagerman

"""

subs=((r'a([nu])',r'u\1'),

(r'A([nu])',r'U\1'),

(r'a\B',r'e'),

(r'A\B',r'E'),

(r'en\b',r'ee'),

(r'\Bew',r'oo'),

(r'\Be\b',r'e-a'),

(r'\be',r'i'),

(r'\bE',r'I'),

(r'\Bf',r'ff'),

(r'\Bir',r'ur'),

(r'(\w*?)i(\w*?)$',r'\1ee\2'),

(r'\bow',r'oo'),

(r'\bo',r'oo'),

(r'\bO',r'Oo'),

(r'the',r'zee'),

(r'The',r'Zee'),

(r'th\b',r't'),

(r'\Btion',r'shun'),

(r'\Bu',r'oo'),

(r'\BU',r'Oo'),

(r'v',r'f'),

(r'V',r'F'),

(r'w',r'w'),

(r'W',r'W'),

(r'([a-z])[.]',r'\1.BorkBorkBork!'))

classFuddDialectizer(Dialectizer):

"""convertHTMLtoElmerFudd-speak"""

subs=((r'[rl]',r'w'),

(r'qu',r'qw'),

(r'th\b',r'f'),

(r'th',r'd'),

(r'n[.]',r'n,uh-hah-hah-hah.'))

classOldeDialectizer(Dialectizer):

"""convertHTMLtomockMiddleEnglish"""

subs=((r'i([bcdfghjklmnpqrstvwxyz])e\b',r'y\1'),

(r'i([bcdfghjklmnpqrstvwxyz])e',r'y\1\1e'),

(r'ick\b',r'yk'),

(r'ia([bcdfghjklmnpqrstvwxyz])',r'e\1e'),

(r'e[ea]([bcdfghjklmnpqrstvwxyz])',r'e\1e'),

(r'([bcdfghjklmnpqrstvwxyz])y',r'\1ee'),

(r'([bcdfghjklmnpqrstvwxyz])er',r'\1re'),

(r'([aeiou])re\b',r'\1r'),

(r'ia([bcdfghjklmnpqrstvwxyz])',r'i\1e'),

(r'tion\b',r'cioun'),

(r'ion\b',r'ioun'),

(r'aid',r'ayde'),

(r'ai',r'ey'),

(r'ay\b',r'y'),

(r'ay',r'ey'),

(r'ant',r'aunt'),

(r'ea',r'ee'),

(r'oa',r'oo'),

(r'ue',r'e'),

(r'oe',r'o'),

(r'ou',r'ow'),

(r'ow',r'ou'),

(r'\bhe',r'hi'),

(r've\b',r'veth'),

(r'se\b',r'e'),

(r"'s\b",r'es'),

(r'ic\b',r'ick'),

(r'ics\b',r'icc'),

(r'ical\b',r'ick'),

(r'tle\b',r'til'),

(r'll\b',r'l'),

(r'ould\b',r'olde'),

(r'own\b',r'oune'),

(r'un\b',r'onne'),

(r'rry\b',r'rye'),

(r'est\b',r'este'),

(r'pt\b',r'pte'),

(r'th\b',r'the'),

(r'ch\b',r'che'),

(r'ss\b',r'sse'),

(r'([wybdp])\b',r'\1e'),

(r'([rnt])\b',r'\1\1e'),

(r'from',r'fro'),

(r'when',r'whan'))

deftranslate(url,dialectName="chef"):

"""fetchURLandtranslateusingdialect

dialectin("chef","fudd","olde")"""

importurllib

sock=urllib.urlopen(url)

htmlSource=sock.read()

sock.close()

parserName="%sDialectizer"%dialectName.capitalize()

parserClass=globals()[parserName]

parser=parserClass()

parser.feed(htmlSource)

parser.close()

returnparser.output()

deftest(url):

"""testalldialectsagainstURL"""

fordialectin("chef","fudd","olde"):

outfile="%s.html"%dialect

fsock=open(outfile,"wb")

fsock.write(translate(url,dialect))

fsock.close()

importwebbrowser

webbrowser.open_new(outfile)

if__name__=="__main__":

test("http://diveintopython.org/odbchelper_list.html")

8.3.dialect.py

3.2“List” (mockSwedishChef-speak) (TheMuppets),(mockElmerFudd-speak)(BugsBunny) (mockMiddleEnglish)( ) HTML HTML

<divclass="abstract">

<p>Listsawe<spanclass="application">Pydon</span>'swowkhowsedatatype.

Ifyouwonwyexpewiencewifwistsisawwaysin

<spanclass="application">VisuawBasic</span>ow(Godfowbid)dedatastowe

in<spanclass="application">Powewbuiwdew</span>,bwaceyouwsewffow

<spanclass="application">Pydon</span>wists.</p>

</div>

<< 12345678910 sgmllib.py>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>XML <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

9XML9.1.9.2.9.3.XML9.4.Unicode9.5.9.6.9.7.Segue

9.1. Python XML XML XML

XML PythonUnicode getattr

Beingaphilosophymajorisnotrequired,althoughifyouhaveeverhadthemisfortuneofbeingsubjectedtothewritingsofImmanuelKant,youwillappreciatetheexampleprogramalotmorethanifyoumajoredinsomethinguseful,likecomputerscience.

XML SAX“ SimpleAPIforXML” XML8 HTML sgmllib DOM“ DocumentObjectModel” XML Python Python DOM

Python XML

9.1.kgp.py

,

"""KantGeneratorforPython

Generatesmockphilosophybasedonacontext-freegrammar

Usage:pythonkgp.py[options][source]

Options:

-g...,--grammar=...usespecifiedgrammarfileorURL

-h,--helpshowthishelp

-dshowdebugginginformationwhileparsing

Examples:

kgp.pygeneratesseveralparagraphsofKantianphilosophy

kgp.py-ghusserl.xmlgeneratesseveralparagraphsofHusserl

kpg.py"<xrefid='paragraph'/>"generatesaparagraphofKant

kgp.pytemplate.xmlreadsfromtemplate.xmltodecidewhattogenerate

"""

fromxml.domimportminidom

importrandom

importtoolbox

importsys

importgetopt

_debug=0

classNoSourceError(Exception):pass

classKantGenerator:

"""generatesmockphilosophybasedonacontext-freegrammar"""

def__init__(self,grammar,source=None):

self.loadGrammar(grammar)

self.loadSource(sourceandsourceorself.getDefaultSource())

self.refresh()

def_load(self,source):

"""loadXMLinputsource,returnparsedXMLdocument

-aURLofaremoteXMLfile("http://diveintopython.org/kant.xml")

-afilenameofalocalXMLfile("~/diveintopython/common/py/kant.xml")

-standardinput("-")

-theactualXMLdocument,asastring

"""

sock=toolbox.openAnything(source)

xmldoc=minidom.parse(sock).documentElement

sock.close()

returnxmldoc

defloadGrammar(self,grammar):

"""loadcontext-freegrammar"""

self.grammar=self._load(grammar)

self.refs={}

forrefinself.grammar.getElementsByTagName("ref"):

self.refs[ref.attributes["id"].value]=ref

defloadSource(self,source):

"""loadsource"""

self.source=self._load(source)

defgetDefaultSource(self):

"""guessdefaultsourceofthecurrentgrammar

Thedefaultsourcewillbeoneofthe<ref>sthatisnot

cross-referenced.Thissoundscomplicatedbutit'snot.

Example:Thedefaultsourceforkant.xmlis

"<xrefid='section'/>",because'section'istheone<ref>

thatisnot<xref>'danywhereinthegrammar.

Inmostgrammars,thedefaultsourcewillproducethe

longest(andmostinteresting)output.

"""

xrefs={}

forxrefinself.grammar.getElementsByTagName("xref"):

xrefs[xref.attributes["id"].value]=1

xrefs=xrefs.keys()

standaloneXrefs=[eforeinself.refs.keys()ifenotinxrefs]

ifnotstandaloneXrefs:

raiseNoSourceError,"can'tguesssource,andnosourcespecified"

return'<xrefid="%s"/>'%random.choice(standaloneXrefs)

defreset(self):

"""resetparser"""

self.pieces=[]

self.capitalizeNextWord=0

defrefresh(self):

"""resetoutputbuffer,re-parseentiresourcefile,andreturnoutput

Sinceparsinginvolvesagooddealofrandomness,thisisan

easywaytogetnewoutputwithouthavingtoreloadagrammarfile

eachtime.

"""

self.reset()

self.parse(self.source)

returnself.output()

defoutput(self):

"""outputgeneratedtext"""

return"".join(self.pieces)

defrandomChildElement(self,node):

"""choosearandomchildelementofanode

Thisisautilitymethodusedbydo_xrefanddo_choice.

"""

choices=[eforeinnode.childNodes

ife.nodeType==e.ELEMENT_NODE]

chosen=random.choice(choices)

if_debug:

sys.stderr.write('%savailablechoices:%s\n'%\

(len(choices),[e.toxml()foreinchoices]))

sys.stderr.write('Chosen:%s\n'%chosen.toxml())

returnchosen

defparse(self,node):

"""parseasingleXMLnode

AparsedXMLdocument(fromminidom.parse)isatreeofnodes

ofvarioustypes.Eachnodeisrepresentedbyaninstanceofthe

correspondingPythonclass(Elementforatag,Textfor

textdata,Documentforthetop-leveldocument).Thefollowing

statementconstructsthenameofaclassmethodbasedonthetype

ofnodewe'reparsing("parse_Element"foranElementnode,

"parse_Text"foraTextnode,etc.)andthencallsthemethod.

"""

parseMethod=getattr(self,"parse_%s"%node.__class__.__name__)

parseMethod(node)

defparse_Document(self,node):

"""parsethedocumentnode

Thedocumentnodebyitselfisn'tinteresting(tous),but

itsonlychild,node.documentElement,is:it'stherootnode

ofthegrammar.

"""

self.parse(node.documentElement)

defparse_Text(self,node):

"""parseatextnode

Thetextofatextnodeisusuallyaddedtotheoutputbuffer

verbatim.Theoneexceptionisthat<pclass='sentence'>sets

aflagtocapitalizethefirstletterofthenextword.If

thatflagisset,wecapitalizethetextandresettheflag.

"""

text=node.data

ifself.capitalizeNextWord:

self.pieces.append(text[0].upper())

self.pieces.append(text[1:])

self.capitalizeNextWord=0

else:

self.pieces.append(text)

defparse_Element(self,node):

"""parseanelement

AnXMLelementcorrespondstoanactualtaginthesource:

<xrefid='...'>,<pchance='...'>,<choice>,etc.

Eachelementtypeishandledinitsownmethod.Likewedidin

parse(),weconstructamethodnamebasedonthenameofthe

element("do_xref"foran<xref>tag,etc.)and

callthemethod.

"""

handlerMethod=getattr(self,"do_%s"%node.tagName)

handlerMethod(node)

defparse_Comment(self,node):

"""parseacomment

ThegrammarcancontainXMLcomments,butweignorethem

"""

pass

defdo_xref(self,node):

"""handle<xrefid='...'>tag

An<xrefid='...'>tagisacross-referencetoa<refid='...'>

tag.<xrefid='sentence'/>evaluatestoarandomlychosenchildof

<refid='sentence'>.

"""

id=node.attributes["id"].value

self.parse(self.randomChildElement(self.refs[id]))

defdo_p(self,node):

"""handle<p>tag

The<p>tagisthecoreofthegrammar.Itcancontainalmost

anything:freeformtext,<choice>tags,<xref>tags,evenother

<p>tags.Ifa"class='sentence'"attributeisfound,aflag

issetandthenextwordwillbecapitalized.Ifa"chance='X'"

attributeisfound,thereisanX%chancethatthetagwillbe

evaluated(andthereforea(100-X)%chancethatitwillbe

completelyignored)

"""

keys=node.attributes.keys()

if"class"inkeys:

ifnode.attributes["class"].value=="sentence":

self.capitalizeNextWord=1

if"chance"inkeys:

chance=int(node.attributes["chance"].value)

doit=(chance>random.randrange(100))

else:

doit=1

ifdoit:

forchildinnode.childNodes:self.parse(child)

defdo_choice(self,node):

"""handle<choice>tag

A<choice>tagcontainsoneormore<p>tags.One<p>tag

ischosenatrandomandevaluated;therestareignored.

"""

self.parse(self.randomChildElement(node))

defusage():

print__doc__

defmain(argv):

grammar="kant.xml"

try:

opts,args=getopt.getopt(argv,"hg:d",["help","grammar="

exceptgetopt.GetoptError:

usage()

sys.exit(2)

foropt,arginopts:

ifoptin("-h","--help"):

usage()

sys.exit()

elifopt=='-d':

global_debug

_debug=1

elifoptin("-g","--grammar"):

grammar=arg

source="".join(args)

k=KantGenerator(grammar,source)

printk.output()

if__name__=="__main__":

main(sys.argv[1:])

9.2.toolbox.py

"""Miscellaneousutilityfunctions"""

defopenAnything(source):

"""URI,filename,orstring-->stream

Thisfunctionletsyoudefineparsersthattakeanyinputsource

(URL,pathnametolocalornetworkfile,oractualdataasastring)

anddealwithitinauniformmanner.Returnedobjectisguaranteed

tohaveallthebasicstdioreadmethods(read,readline,readlines).

Just.close()theobjectwhenyou'redonewithit.

Examples:

>>>fromxml.domimportminidom

>>>sock=openAnything("http://localhost/kant.xml")

>>>doc=minidom.parse(sock)

>>>sock.close()

>>>sock=openAnything("c:\\inetpub\\wwwroot\\kant.xml")

>>>doc=minidom.parse(sock)

>>>sock.close()

>>>sock=openAnything("<refid='conjunction'><text>and</text><text>or</text></ref>")

>>>doc=minidom.parse(sock)

>>>sock.close()

"""

ifhasattr(source,"read"):

returnsource

ifsource=='-':

importsys

returnsys.stdin

#trytoopenwithurllib(ifsourceishttp,ftp,orfileURL)

importurllib

try:

returnurllib.urlopen(source)

except(IOError,OSError):

pass

#trytoopenwithnativeopenfunction(ifsourceispathname)

try:

returnopen(source)

except(IOError,OSError):

pass

#treatsourceasstring

importStringIO

returnStringIO.StringIO(str(source))

kgp.py kant.xml XML

9.3.Sampleoutputofkgp.py

[you@localhostkgp]$pythonkgp.py

AsisshowninthewritingsofHume,ouraprioriconcepts,in

referencetoends,abstractfromallcontentofknowledge;inthestudy

ofspace,thedisciplineofhumanreason,inaccordancewiththe

principlesofphilosophy,isthecluetothediscoveryofthe

TranscendentalDeduction.Thetranscendentalaesthetic,inall

theoreticalsciences,occupiespartofthesphereofhumanreason

concerningtheexistenceofourideasingeneral;still,the

never-endingregressintheseriesofempiricalconditionsconstitutes

thewholecontentforthetranscendentalunityofapperception.What

wehavealonebeenabletoshowisthat,evenasthisrelatestothe

architectonicofhumanreason,theIdealmaynotcontradictitself,but

itisstillpossiblethatitmaybeincontradictionswiththe

employmentofthepureemploymentofourhypotheticaljudgements,but

naturalcauses(andIassertthatthisisthecase)provethevalidity

ofthedisciplineofpurereason.Aswehavealreadyseen,time(and

itisobviousthatthisistrue)provesthevalidityoftime,andthe

architectonicofhumanreason,inthefullsenseoftheseterms,

abstractsfromallcontentofknowledge.Iassert,inthecaseofthe

disciplineofpracticalreason,thattheAntinomiesarejustas

necessaryasnaturalcauses,sinceknowledgeofthephenomenaisa

posteriori.

Thedisciplineofhumanreason,asIhaveelsewhereshown,isby

itsverynaturecontradictory,butourideasexcludethepossibilityof

theAntinomies.Wecandeducethat,onthecontrary,thepure

employmentofphilosophy,onthecontrary,isbyitsverynature

contradictory,butoursenseperceptionsarearepresentationof,in

thecaseofspace,metaphysics.Thethinginitselfisa

representationofphilosophy.Appliedlogicisthecluetothe

discoveryofnaturalcauses.However,whatwehavealonebeenableto

showisthatourideas,inotherwords,shouldonlybeusedasacanon

fortheIdeal,becauseofournecessaryignoranceoftheconditions.

[...snip...]

kant.xml

9.4.kgp.py

[you@localhostkgp]$pythonkgp.py-gbinary.xml

00101001

[you@localhostkgp]$pythonkgp.py-gbinary.xml

10110100

kgp.py

<< 1234567 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>ScriptsStreams <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

10ScriptsStreams10.1.10.2.10.3.10.4.10.5.Creatingseparatehandlersbynodetype10.6.10.7.10.8.

10.1.Python (file-like)

read size size size size

read

XML minidom.parse

10.1. XML

>>>fromxml.domimportminidom

>>>fsock=open('binary.xml')

>>>xmldoc=minidom.parse(fsock)

>>>fsock.close()

>>>printxmldoc.toxml()

<?xmlversion="1.0"?>

<grammar>

<refid="bit">

<p>0</p>

<p>1</p>

</ref>

<refid="byte">

<p><xrefid="bit"/><xrefid="bit"/><xrefid="bit"/><xrefid="bit"/>\

<xrefid="bit"/><xrefid="bit"/><xrefid="bit"/><xrefid="bit"/></p>

</ref>

</grammar>

minidom.parsefsock read XML

close minidom.parse

XMLtoxml()

minidom.parse minidom.parse™Internet XML

10.2. URL XML

>>>importurllib

>>>usock=urllib.urlopen('http://slashdot.org/slashdot.rdf')

>>>xmldoc=minidom.parse(usock)

>>>usock.close()

>>>printxmldoc.toxml()

<?xmlversion="1.0"?>

<rdf:RDFxmlns="http://my.netscape.com/rdf/simple/0.9/"

xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">

<channel>

<title>Slashdot</title>

<link>http://slashdot.org/</link>

<description>Newsfornerds,stuffthatmatters</description>

</channel>

<image>

<title>Slashdot</title>

<url>http://images.slashdot.org/topics/topicslashdot.gif</url>

<link>http://slashdot.org/</link>

</image>

<item>

<title>ToHDTVorNottoHDTV?</title>

<link>http://slashdot.org/article.pl?sid=01/12/28/0421241</link>

</item>

[...snip...]

urlopenweb URL readweb HTML minidom.parse read read XML XMLweb

minidom.parsewebweb urlopen URL XMLSlashdot XML

10.3. XML()

>>>contents="<grammar><refid='bit'><p>0</p><p>1</p></ref></grammar>"

>>>xmldoc=minidom.parseString(contents)

>>>printxmldoc.toxml()

<?xmlversion="1.0"?>

<grammar><refid="bit"><p>0</p><p>1</p></ref></grammar>

minidom parseString XML XMLminidom.parse

OK minidom.parse URL... URLparseString

minidom.parse StringIO

10.4.StringIO

>>>contents="<grammar><refid='bit'><p>0</p><p>1</p></ref></grammar>"

>>>importStringIO

>>>ssock=StringIO.StringIO(contents)

>>>ssock.read()

"<grammar><refid='bit'><p>0</p><p>1</p></ref></grammar>"

>>>ssock.read()

''

>>>ssock.seek(0)

>>>ssock.read(15)

'<grammar><refi'

>>>ssock.read(15)

"d='bit'><p>0</p"

>>>ssock.read()

'><p>1</p></ref></grammar>'

>>>ssock.close()

StringIO StringIO StringIO

read read StringIO StringIO seeksize read

read

10.5. XML

>>>contents="<grammar><refid='bit'><p>0</p><p>1</p></ref></grammar>"

>>>ssock=StringIO.StringIO(contents)

>>>xmldoc=minidom.parse(ssock)

>>>ssock.close()

>>>printxmldoc.toxml()

<?xmlversion="1.0"?>

<grammar><refid="bit"><p>0</p><p>1</p></ref></grammar>

StringIO minidom.parse read

minidom.parseweb XMLweb urlopen open

StringIO

10.6.openAnything

defopenAnything(source):

#trytoopenwithurllib(ifsourceishttp,ftp,orfileURL)

importurllib

try:

returnurllib.urlopen(source)

except(IOError,OSError):

pass

#trytoopenwithnativeopenfunction(ifsourceispathname)

try:

returnopen(source)

except(IOError,OSError):

pass

#treatsourceasstring

importStringIO

returnStringIO.StringIO(str(source))

openAnything source source URL'http://slashdot.org/slashdot.rdf' 'binary.xml'

XMLsource URL URL URL urllib URL

urllibsource return try

urllibsource URL source

source StringIO str source

__str__

openAnything minidom.parse XMLsourcesource URL XML

10.7. kgp.py openAnything

classKantGenerator:

def_load(self,source):

sock=toolbox.openAnything(source)

xmldoc=minidom.parse(sock).documentElement

sock.close()

returnxmldoc

<<Segue 12345678 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>FunctionalProgramming <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

16FunctionalProgramming16.1.16.2.16.3.16.4.16.5.16.6.16.7.16.8.

16.1. 13 14 Python 15 Python

regression Python 13 roman.py

16.1.regression.py

,

"""Regressiontestingframework

Thismodulewillsearchforscriptsinthesamedirectorynamed

XYZtest.py.Eachsuchscriptshouldbeatestsuitethattestsa

modulethroughPyUnit.(AsofPython2.1,PyUnitisincludedin

thestandardlibraryas"unittest".)Thisscriptwillaggregateall

foundtestsuitesintoonebigtestsuiteandrunthemallatonce.

"""

importsys,os,re,unittest

defregressionTest():

path=os.path.abspath(os.path.dirname(sys.argv[0]))

files=os.listdir(path)

test=re.compile("test\.py$",re.IGNORECASE)

files=filter(test.search,files)

filenameToModuleName=lambdaf:os.path.splitext(f)[0]

moduleNames=map(filenameToModuleName,files)

modules=map(__import__,moduleNames)

load=unittest.defaultTestLoader.loadTestsFromModule

returnunittest.TestSuite(map(load,modules))

if__name__=="__main__":

unittest.main(defaultTest="regressionTest")

test.py

16.2.regression.py

[you@localhostpy]$pythonregression.py-v

helpshouldfailwithnoobject...ok

helpshouldreturnknownresultforapihelper...ok

helpshouldhonorcollapseargument...ok

helpshouldhonorspacingargument...ok

buildConnectionStringshouldfailwithlistinput...ok

buildConnectionStringshouldfailwithstringinput...ok

buildConnectionStringshouldfailwithtupleinput...ok

buildConnectionStringhandlesemptydictionary...ok

buildConnectionStringreturnsknownresultwithknowninput...ok

fromRomanshouldonlyacceptuppercaseinput...ok

toRomanshouldalwaysreturnuppercase...ok

fromRomanshouldfailwithblankstring...ok

fromRomanshouldfailwithmalformedantecedents...ok

fromRomanshouldfailwithrepeatedpairsofnumerals...ok

fromRomanshouldfailwithtoomanyrepeatednumerals...ok

fromRomanshouldgiveknownresultwithknowninput...ok

toRomanshouldgiveknownresultwithknowninput...ok

fromRoman(toRoman(n))==nforalln...ok

toRomanshouldfailwithnon-integerinput...ok

toRomanshouldfailwithnegativeinput...ok

toRomanshouldfailwithlargeinput...ok

toRomanshouldfailwith0input...ok

kgpareftest...ok

kgpbreftest...ok

kgpcreftest...ok

kgpdreftest...ok

kgpereftest...ok

kgpfreftest...ok

kgpgreftest...ok

----------------------------------------------------------------------

Ran29testsin2.799s

OK

apihelpertest.py 4 odbchelpertest.py 2 Python

romantest.py 13

<< 12345678 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython>HTTPWeb <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

11HTTPWeb11.1.11.2.HTTP11.3.HTTP

11.3.1.(User-Agent)11.3.2.(Redirects)11.3.3.Last-Modified/If-Modified-Since11.3.4.ETag/If-None-Match11.3.5.(Compression)

11.4.HTTPweb11.5.User-Agent11.6.Last-ModifiedETag11.7.11.8.11.9.11.10.

11.1. web URLXML , HTML XMLHTTPweb

,HTTPwebHTTP,HTTPGET;,HTTPPOST(HTTPwebAPIHTTPPUTHTTPDELETE)“ verbs ”(GET,POST,PUTDELETE),,

XML,HTTP

HTTPwebXML:

AmazonAPIAmazon.comNationalWeatherService() HongKongObservatory()web

AtomAPIwebSyndicatedfeedsweblogs

,HTTPAPI,HTTPGET,HTTPwebHTTP

openanything:

11.1.openanything.py

,

importurllib2,urlparse,gzip

fromStringIOimportStringIO

USER_AGENT='OpenAnything/1.0+http://diveintopython.org/http_web_services/'

classSmartRedirectHandler(urllib2.HTTPRedirectHandler):

defhttp_error_301(self,req,fp,code,msg,headers):

result=urllib2.HTTPRedirectHandler.http_error_301(

self,req,fp,code,msg,headers)

result.status=code

returnresult

defhttp_error_302(self,req,fp,code,msg,headers):

result=urllib2.HTTPRedirectHandler.http_error_302(

self,req,fp,code,msg,headers)

result.status=code

returnresult

classDefaultErrorHandler(urllib2.HTTPDefaultErrorHandler):

defhttp_error_default(self,req,fp,code,msg,headers):

result=urllib2.HTTPError(

req.get_full_url(),code,msg,headers,fp)

result.status=code

returnresult

defopenAnything(source,etag=None,lastmodified=None,agent=USER_AGENT):

'''URL,filename,orstring-->stream

Thisfunctionletsyoudefineparsersthattakeanyinputsource

(URL,pathnametolocalornetworkfile,oractualdataasastring)

anddealwithitinauniformmanner.Returnedobjectisguaranteed

tohaveallthebasicstdioreadmethods(read,readline,readlines).

Just.close()theobjectwhenyou'redonewithit.

Iftheetagargumentissupplied,itwillbeusedasthevalueofan

If-None-Matchrequestheader.

Ifthelastmodifiedargumentissupplied,itmustbeaformatted

date/timestringinGMT(asreturnedintheLast-Modifiedheaderof

apreviousrequest).Theformatteddate/timewillbeused

asthevalueofanIf-Modified-Sincerequestheader.

Iftheagentargumentissupplied,itwillbeusedasthevalueofa

User-Agentrequestheader.

'''

ifhasattr(source,'read'):

returnsource

ifsource=='-':

returnsys.stdin

ifurlparse.urlparse(source)[0]=='http':

#openURLwithurllib2

request=urllib2.Request(source)

request.add_header('User-Agent',agent)

ifetag:

request.add_header('If-None-Match',etag)

iflastmodified:

request.add_header('If-Modified-Since',lastmodified)

request.add_header('Accept-encoding','gzip')

opener=urllib2.build_opener(SmartRedirectHandler(),DefaultErrorHandler())

returnopener.open(request)

#trytoopenwithnativeopenfunction(ifsourceisafilename)

try:

returnopen(source)

except(IOError,OSError):

pass

#treatsourceasstring

returnStringIO(str(source))

deffetch(source,etag=None,last_modified=None,agent=USER_AGENT):

'''FetchdataandmetadatafromaURL,file,stream,orstring'''

result={}

f=openAnything(source,etag,last_modified,agent)

result['data']=f.read()

ifhasattr(f,'headers'):

#saveETag,iftheserversentone

result['etag']=f.headers.get('ETag')

#saveLast-Modifiedheader,iftheserversentone

result['lastmodified']=f.headers.get('Last-Modified')

iff.headers.get('content-encoding','')=='gzip':

#datacamebackgzip-compressed,decompressit

result['data']=gzip.GzipFile(fileobj=StringIO(result[

ifhasattr(f,'url'):

result['url']=f.url

result['status']=200

ifhasattr(f,'status'):

result['status']=f.status

f.close()

returnresult

PaulPrescod HTTPwebInternet

<< 12345678910 HTTP>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

1313.1.II13.2.13.3.romantest.py13.4.Testingforsuccess13.5.Testingforfailure13.6.Testingforsanity

13.1.II“ ”" Python

7.3“”

1.2. .3. 1 3999 1000 1 39994. 0 0)5.6.

roman.py

1. toRoman 1 39992. toRoman 1 39993. toRoman4. fromRoman5. fromRoman6. fromRoman(toRoman(n))==n 1..3999 n7. toRoman8. fromRoman

<< 123456 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

1515.1.bugs15.2.15.3.15.4.15.5.

15.1.bugsbug“ bug”Bug

15.1.Bug

>>>importroman5

>>>roman5.fromRoman("")

0

BugInvalidRomanNumeralError

Bug

15.2.bug romantest61.py

classFromRomanBadInput(unittest.TestCase):

#previoustestcasesomittedforclarity(theyhaven'tchanged)

deftestBlank(self):

"""fromRomanshouldfailwithblankstring"""

self.assertRaises(roman.InvalidRomanNumeralError,roman.fromRoman,

fromRoman InvalidRomanNumeralErrorBug

BugBug

15.3. romantest61.py roman61.py

fromRomanshouldonlyacceptuppercaseinput...ok

toRomanshouldalwaysreturnuppercase...ok

fromRomanshouldfailwithblankstring...FAIL

fromRomanshouldfailwithmalformedantecedents...ok

fromRomanshouldfailwithrepeatedpairsofnumerals...ok

fromRomanshouldfailwithtoomanyrepeatednumerals...ok

fromRomanshouldgiveknownresultwithknowninput...ok

toRomanshouldgiveknownresultwithknowninput...ok

fromRoman(toRoman(n))==nforalln...ok

toRomanshouldfailwithnon-integerinput...ok

toRomanshouldfailwithnegativeinput...ok

toRomanshouldfailwithlargeinput...ok

toRomanshouldfailwith0input...ok

======================================================================

FAIL:fromRomanshouldfailwithblankstring

----------------------------------------------------------------------

Traceback(mostrecentcalllast):

File"C:\docbook\dip\py\roman\stage6\romantest61.py",line137,intestBlank

self.assertRaises(roman61.InvalidRomanNumeralError,roman61.fromRoman,"")

File"c:\python21\lib\unittest.py",line266,infailUnlessRaises

raiseself.failureException,excName

AssertionError:InvalidRomanNumeralError

----------------------------------------------------------------------

Ran13testsin2.864s

FAILED(failures=1)

Bug

15.4.Bug roman62.py

py/roman/stage6/

deffromRoman(s):

"""convertRomannumeraltointeger"""

ifnots:

raiseInvalidRomanNumeralError,'Inputcannotbeblank'

ifnotre.search(romanNumeralPattern,s):

raiseInvalidRomanNumeralError,'InvalidRomannumeral:%s'

result=0

index=0

fornumeral,integerinromanNumeralMap:

whiles[index:index+len(numeral)]==numeral:

result+=integer

index+=len(numeral)

returnresult

raise

15.5. romantest62.py roman62.py

fromRomanshouldonlyacceptuppercaseinput...ok

toRomanshouldalwaysreturnuppercase...ok

fromRomanshouldfailwithblankstring...ok

fromRomanshouldfailwithmalformedantecedents...ok

fromRomanshouldfailwithrepeatedpairsofnumerals...ok

fromRomanshouldfailwithtoomanyrepeatednumerals...ok

fromRomanshouldgiveknownresultwithknowninput...ok

toRomanshouldgiveknownresultwithknowninput...ok

fromRoman(toRoman(n))==nforalln...ok

toRomanshouldfailwithnon-integerinput...ok

toRomanshouldfailwithnegativeinput...ok

toRomanshouldfailwithlargeinput...ok

toRomanshouldfailwith0input...ok

----------------------------------------------------------------------

Ran13testsin2.834s

OK

BugBug

BugBugBugBugBugBugregressiontest

<<roman.py,5 12345 >>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

1717.1.17.2.plural.py,117.3.plural.py,217.4.plural.py,317.5.plural.py,417.6.plural.py,517.7.plural.py,617.8.

17.1.Generator Python2.3

7

1. SXZES “Bass”“ basses”“ fax”“ faxes“waltz”“ waltzes”

2. HESHSH“ coach”“coaches”“ rash”“ rashes”CHSH“cheetah”“ cheetahs”H

3. IYYIESYS“ vacancy”“vacancies”“ day”“ days”.

4. S

“ Man”“ men”“ woman”“ women”“ human”“humans”“ Mouse”“ mice”“ louse”“ lice”“ house”“houses”“ Knife”“ knives”“ wife”“ wives”“ lowlife”“lowlifes”“ sheep”,“deer”“ haiku”

<< 12345678 plural.py,1>>

©2000,2001,2002,2003,2004 MarkPilgrim

: >DiveIntoPython> <<>>

Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]

1818.1.18.2.timeit18.3.18.4.18.5.18.6.18.7.

(Performancetuning) Python

18.1.

()

PythonSoundexSoundex20SoundexSoundex

Soundex

1.2.

BFPV1CGJKQSXZ2.DT3.L4.MN5.R6.9.

3.4. 95.6.

PilgrimP9426959P4265P426

WooW99W9WW000

Soundex

18.1.soundex/stage1/soundex1a.py

,

importstring,re

charToSoundex={"A":"9",

"B":"1",

"C":"2",

"D":"3",

"E":"9",

"F":"1",

"G":"2",

"H":"9",

"I":"9",

"J":"2",

"K":"2",

"L":"4",

"M":"5",

"N":"5",

"O":"9",

"P":"1",

"Q":"2",

"R":"6",

"S":"2",

"T":"3",

"U":"9",

"V":"1",

"W":"9",

"X":"2",

"Y":"9",

"Z":"2"}

defsoundex(source):

"convertstringtoSoundexequivalent"

#Soundexrequirements:

#sourcestringmustbeatleast1character

#andmustconsistentirelyofletters

allChars=string.uppercase+string.lowercase

ifnotre.search('^[%s]+$'%allChars,source):

return"0000"

#Soundexalgorithm:

#1.makefirstcharacteruppercase

source=source[0].upper()+source[1:]

#2.translateallothercharacterstoSoundexdigits

digits=source[0]

forsinsource[1:]:

s=s.upper()

digits+=charToSoundex[s]

#3.removeconsecutiveduplicates

digits2=digits[0]

fordindigits[1:]:

ifdigits2[-1]!=d:

digits2+=d

#4.removeall"9"s

digits3=re.sub('9','',digits2)

#5.padendwith"0"sto4characters

whilelen(digits3)<4:

digits3+="0"

#6.returnfirst4characters

returndigits3[:4]

if__name__=='__main__':

fromtimeitimportTimer

names=('Woo','Pilgrim','Flingjingwaller')

fornameinnames:

statement="soundex('%s')"%name

t=Timer(statement,"from__main__importsoundex")

printname.ljust(15),soundex(name),min(t.repeat())

SoundexingandGenealogySoundex

<< 1234567 timeit>>

©2000,2001,2002,2003,2004 MarkPilgrim

Recommended