Post on 21-Jul-2020
Python(DiveIntoPython)Python[DIP_5_4_CPUG_RELEASE]
DiveIntoPython Python
DiveIntoPython Updated2004520
DiveIntoPythonHTMLHTML(singlefile)CHMXML(DocBook)Buildscripts()
DiveIntoPython GNUFreeDocumentationLicense DiveIntoPython
DiveIntoPython?? CD-ROM? GNUFreeDocumentationLicense,GeneralPublicLicense, FDL GPL
©2000,2001,2002,2003,2004 MarkPilgrim
PythonActivePython(,Windows)
IDLE(,Windows)
Komodo(,Windows)
RPMs(,Linux)
()
Emacs python-mode
JackJansenbinaries (, MacOS,MacOSX)
Fink(, MacOSX)
Jython(, Java)
PythonLearningtoProgram
HowtoThinkLikeaComputerScientist
ThinkinginPython
Introductions
O'ReillyPythonCenter
PythonPython.org
python.cn
Pythonic
comp.lang.python
c.l.p.announce
Tutor
Pythonmailinglists
python-chinesemailinglists
python-cnmailinglists(googlegroups)
PythonPythonCookbook
VaultsofParnassus
Python.faqts
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>>
: >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>>
: >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 ,
PythonReferenceManual Python,,eff-bot Python.
<< 123456 >>
©2000,2001,2002,2003,2004 MarkPilgrim
: >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
HowtoThinkLikeaComputerScientisttuple tuplePythonKnowledgeBase tuplePythonTutorial tuple
<<List 12345678 >>
©2000,2001,2002,2003,2004 MarkPilgrim
: >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>>
: >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
: >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“ ”
PythonTutorial list
<< 123456789 typestrdir>>
©2000,2001,2002,2003,2004 MarkPilgrim
: >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...]
Python Pythonman Python
PythonLibraryReference
<< 123456789 getattr>>
©2000,2001,2002,2003,2004 MarkPilgrim
: >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
PythonTutorial lambdaPEP227 PythonTheWholePythonFAQ lambda
<<andor 123456789 >>
©2000,2001,2002,2003,2004 MarkPilgrim
: >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 >>
: >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
PythonTutorial
<< 12345678910 >>
©2000,2001,2002,2003,2004 MarkPilgrim
: >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
: >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()])
:
try...except try...finally for os
<< 1234567 >>
: >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
: >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)
  SGMLParser handle_charref(Entityreference)
HTML © 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>>
: >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 for experienced 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   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 >>
: >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>>
: >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,
: >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 >>
: >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 >>
: >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
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>>
: >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
: >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
: >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 ”
: >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]
A.1Python
2Python
2.3.
PEP257 docstringPythonStyleGuide docstring
PythonTutorial docstring
2.4.2.
PythonReferenceManual Python,,eff-bot Python.
2.5.
PythonReferenceManual,PythonStyleGuide
2.6.
PythonReferenceManual
3
3.1.3.dictionary
HowtoThinkLikeaComputerScientistdictionarydictionaryPythonKnowledgeBase dictionary
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
9XML
9.4.Unicode
Unicode.orgunicodeUnicode Pythonunicodeunicode ASCIIPEP263 .py
10ScriptsStreams
11HTTPWeb
11.1.
PaulPrescod HTTPwebInternet
12SOAPWeb
12.1.
http://www.xmethods.net/ SOAPwebSOAP SOAP
12.8.SOAP
NewdevelopmentsforSOAPpy SOAP
13
13.1.II
13.3.romantest.py
PyUnit unittestPyUnitFAQ PythonLibraryReference unittestExtremeProgramming.orgThePortlandPatternRepository
14
15
15.5.
XProgramming.com
16FunctionalProgramming
17
17.7.plural.py,6
PEP255PythonCookbook .
18
18.1.
SoundexingandGenealogySoundex
<< >>
©2000,2001,2002,2003,2004 MarkPilgrim
: >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()])
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 >>
: >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']
,,,
“ 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" ",refwillbe"160"
#Reconstructtheoriginalcharacterreference.
self.pieces.append("&#%(ref)s;"%locals())
defhandle_entityref(self,ref):
#calledforeachentityreference,e.g.for"©",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
: >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