Errata

Python Cookbook

Errata for Python Cookbook

Submit your own errata for this product.

The errata list is a list of errors and their corrections that were found after the product was released.

The following errata were submitted by our customers and have not yet been approved or disproved by the author or editor. They solely represent the opinion of the customer.

Color Key: Serious technical mistake Minor technical mistake Language or formatting error Typo Question Note Update

Version Location Description Submitted by Date submitted
PDF Page 1
n/a request for change to file name convention

This is not an error, but a comment on the file naming conventions of the examples. That is, when the examples are sorted by filename, they are out of sequence order. (the first file is cb2_10_10_sol_1.py) If you insert 0 for those (sub-/)sections numbered 9 or less filename sort ought to sequence this correctly.

BrendanS  Feb 27, 2009 
Printed Page 5
third code example

1) A blank space should precede the backslash in line 1.
2) This code doesn't seem to work unless line 2 starts at column 1, thus breaking indentation rules.

class TestText:
def test_multiple_lines(self):
big = "This is a long string
that spans two lines."
assert big == 'This is a long string that spans two lines.',
'Error for %s' % big

(test_text.TestText.test_multiple_lines ... ok)

Anonymous   
12.6.2
Section: Converting an XML Document into a tree of Python Objects

BOOK: Python Cookbook by Alex Martelli; Anna Martelli Ravenscroft; David
Ascher
PUBLISHER: O'Reilly Media, Inc.
DATE OF PUBLICATION: March 18, 2005
Chapter 12. Processing XML
Section: Converting an XML Document into a tree of Python Objects
12.6.2 Solution

[Code... snippet]
def EndElement(self, name):
'Expat end element event handler'
self.nodeStack[-1].pop( )

The code above attempts execute the method pop on an Element object
contained in the nodeStack(list). However, there is no method pop defined
in the Element Class. I believe that it was the authors intention to write.

[Code... snippet]
def EndElement(self, name):
'Expat end element event handler'
self.nodeStack.pop( )

Which pops an element of the stack.

Anonymous  Jan 21, 2009 
PDF Page 28
France

The example code about "compress" is shown to return a value that is different from the value obtained in practice.

From the book:

>>> list(compress(addresses, more5))
['5800 E 58TH', '4801 N BROADWAY', '1039 W GRANVILLE']

Actual result:

['5800 E 58TH', '1060 W ADDISON', '4801 N BROADWAY']

Christophe Junke  Jan 20, 2015 
Printed Page 56
Code: "def updateFontState(self):"

The "updateFontState()" function appears to be missing the leading underscore:

"def updateFontState(self):"

should be

"def _updateFontState(self):"

As it stands an error is generated:

AttributeError: TtyFormatter instance has no attribute '_updateFontState'

which is fixed on adding the underscore.

Anonymous  Dec 17, 2013 
Printed, Other Digital Version Page 56
Code

Downloadable code has same error as printed error mentioned above:

updatedFontState(self):

missing leading underscore.

Also, a lot of the code isn't indented correctly.

Anonymous  Dec 17, 2013 
Printed Page 68
2nd and 3rd line

The code reads output.close() instead of output_file.close() and input.close() instead of input_file.close()

This results in the following error:
Traceback (most recent call last):
File "./replace", line 18, in <module>
output.close()
NameError: name 'output' is not defined

Anonymous   
Printed Page 89
Solution: code listing

The last argument passed in to all_files() - yield_folders
doesn't do what its name implies.

The function returns the same output whether yield_folders is set to True or False.

The Directory Walker solution in the first edition of this book has a similar problem.

One solution:
remove these lines

if return_folders:
files.extend(subdirs)

and change this:
if fnmatch.fnmatch(name, pattern):
yield os.path.join(path, name)
break

to this:

if fnmatch.fnmatch(name, pattern):
if return_folders:
yield path, os.path.join(path, name)
else:
yield os.path.join(path, name)
break

Anonymous  Apr 15, 2010 
Printed Page 96
comments in the code (Solution) of recipe 2.22, second function called 'common_prefix'

I may have found something worth correcting and would like to share it with you. The apparent mistake can be found on page 96 in the comments in the code (Solution) of recipe 2.22 "Computing the relative path from one directory to another".

The comments on the code refer to "unique tails", this statement isn't always true. There are several ways in which the resulting tails would not be unique. This is an example to illustrate this:
>>> li1 = [1,2,3,4]
>>> li2 = [1,2,4,5]
>>> li3 = [1,2,4,5]
>>> common_prefix(li1, li2, li3)
([1, 2], [[3, 4], [4, 5], [4, 5]])

As you may see the second element in the tuple - the list containing the 'tails' - contains the 'tail' [4, 5] twice. I'm using numbers here for the sake of the example but for paths the same is off course true.

Anonymous   
PDF Page 108
crc64digest subroutine

I'm a novice programmer, but I think I found an error in Recipe 2.30.

I couldn't get the program to work with Python 2.7 or 3.1, so I looked closely and found something that didn't look right. "bytes" isn't defined as a global as far as I could tell, so I tried a substitution.

In PDF:
def crc64digest(aString):
return "%08X%08X" % (crc64(bytes))

What seems to work:
def crc64digest(aString):
return "%08X%08X" % (crc64(aString))

Hopefully, this simple fix corrects the issue, but if not, there still appears to be a problem with the program.

Thanks,
Brian Rock

Catbar  Aug 08, 2011 
Printed Page 124
Recipe 3.6

Boxing day is the day after Christmas, not the day after Easter.

Anonymous   
Printed Page 132
code snippet "if numargs < 3"

By the time this statement is executed we had already determined that there must be either 1 or 2 command line args passed in otherwise the script would have exited. However now we are checking whether numargs < 3 where numargs = len(sys.argv) - 1. This condition will always be true i.e. if len(sys.argv) = 3 then numargs = 2 and numargs will always be less than 3, therefore the else clause will never be executed AFAICT.

Anonymous   
Printed Page 166
1st paragraph

About the timing of the different "Adding an Entry to a Dictionary" algorithms, you write, "Taking the first version of addword in the recipe as a reference point, the second one (using try/except) is about 10% faster, the third one (using setdefault) is about 20% slower[.]" But the order of the definitions on the previous page is setdefault first, if/else second, and try/except third.

{201/202} Code;
The return value of the hist.counts method in the code snippet is just the list of
keys sorted by values. However, on the example on the next page at the bottom it's
outputting keys and value combinations.

Anonymous   
Printed, Other Digital Version Page 176
1st line

The source code listing has

return tokenDict[word]()

Running the code example throws the error:
SyntaxError: 'return' outside function

which is right, this code is not within a function.

Delete 'return' and the code example runs.

Deborah Pollard  Feb 22, 2012 
Printed Page 240
Recipe 6.3

Recipe 6.3 doesn't (seem to) work because the overrridden __setattr__ also operates during __init__ i.e. you cannot set any attributes at all...

Anonymous   
Printed Page 271
code in solution to 6.15

The line

cls._inst = type.__new__(cls, *args, **args)

should read

cls._inst = object.__new__(cls, *args, **args)

Anonymous   
Printed Page 272
1st code block, first and third lines from bottom

Instance objects s1 and s2 have no method 'spam()', therefore these two line will
cause AttributeError. Do the authors intend to print 's1.s' and 's2.s' instead of
's1.spam()' and 's2.spam()'?

Anonymous   
Printed Page 277
code at bottom of page

def __new__(cls, *args, **kwargs):
if '_inst' not in vars(cls):
cls._inst = type.__new__(cls, *args, **kwargs)

return cls._inst


should be (type changed to super...):


def __new__(cls, *args, **kwargs):
if '_inst' not in vars(cls):
cls._inst = super(Null, cls).__new__(cls, *args, **kwargs)

return cls._inst

Anonymous  Nov 03, 2008 
Printed Page 312
2

After inserting values into the db, the connection.commit() is missing. Without it the data won't get into the database.

Gy?rgy Div?s  Mar 16, 2009 
Printed Page 353
first code example, 7th line

if not (second-error) < first < (second-error):
should read:
if not (second-error) < first < (second+error):

Anonymous   
Printed Page 413
in code sample, beginning of page

wr.SetValueEx(..., REG_SZ,..) => wr.REG_SZ

after both finally:
CloseKey(...) => wr.CloseKey(...)

Anonymous   
Printed Page 420
1st paragraph

Solution Code as printed results in error:
Traceback (most recent call last):
File "/Users/local/Desktop/test.py", line 834, in <module>
main ()
File "/Users/local/Desktop/test.py", line 414, in main
print '%s: %s' % (k, info[k][0])
File "/Users/local/Desktop/test.py", line 93, in __getitem__
from xml import xpath
ImportError: cannot import name xpath

Anonymous  Aug 02, 2009 
Printed Page 449
Near the middle of the Solution code listing

for k, v in kw:
should be
for k, v in kw.iteritems():

Anonymous   
Printed Page 472
Recipe 12.5 code: class Xml2Obj, func EndElement

In this code:

def EndElement(self, name):
'Expat end element event handler'
self.nodeStack[-1].pop( )

the last line is wrong. It should read:

self.nodeStack.pop( )

Anonymous   
Printed Page 472
Middle (in code)

I'm a newbie, so maybe I'm missing something, but I think there is a slight mistake in a recipe in the Python Cookbook (2nd Ed., 2005). I'm also submitting this on the O'Reilly site.

12.5 Converting an XML Document into a Tree of Python Objects (p.471-472)

Cookbook code:

class Xml2Obj:
EndElement():
...
self.nodeStack[-1].pop()

Suggested code:
self.nodeStack.pop(-1)

With that change, the recipe works (python version 2.5) -- without it, it bombs.

nodeStack is a list of Element objects. Element objects gather up the tagnames, attributes, and a list of children elements of Element nodes in an XML object. They aren't lists and don't have a pop() method. But the code pulls the last Element off the nodeStack, and calls pop() on that Element.

The suggested code call pop() on nodeStack, which is a list, pulling off the last of its elements.

Gordon Agress  Jul 15, 2009 
Printed Page 495
python code sample at bottom of page

line 3 of example: import mimetypes, email.Generator, email.Message

line 10 of example: mainMsg = email.Message.Message( )

results in:

Traceback (most recent call last):
File "/home/f85/noonan/bin/gradetools/htmlmail.py", line ?, in ?
mainMsg = email.Message()
AttributeError: 'dict' object has no attribute 'Message'

Anonymous   
Printed Page 561
solution code

Server references meerkat which is no longer available.

Anonymous   
Printed Page 562
first code snippet and paragraphs before and after

The "main point" described here appears to be completely wrong.

The book says "...an instance object with the right attributes works just as well as
a dictionary object..."

But the documentation for xmlrpclib says "Note that even though starting with Python
2.2 you can subclass builtin types, the xmlrpclib module currently does not marshal
instances of such subclasses."

The docs are right. The implementation of xmlrpclib dispatches function parameters
using type(value), not isinstance(value), so it can't handle anything but its short
list of known (built-in) types.

The variant code on this page just prints:

TypeError: cannot marshal <class '__main__.MeerkatQuery'> objects

Anonymous   
Printed Page 672
first para code sample def _bytes_to_bits():

def _bytes_to_bits():
...
for n in xrange(256):
...
n >>= 1
...
the_table[n] = ''.join(bits)

# The bit-shifting of variable n changes its value, therefore it is # no longer valid as the list index to the_table.

# to fix, you need to bit-shift a copy of n:

def _bytes_to_bits():
...
for n in xrange(256):
q = n
...
bits[i] = '01'[q & 1]
q >>= 1
...
the_table[n] = ''.join(bits)

______________
Incidentally I found that the following code was 7.5 % faster when converting 11 million dotted quad ip addresses to a binary string.

def bigendbits(ip):
for q in ip:
q = int(q)
for b in range(0,8):
yield 1 if (q & 128) else 0
q = q << 1

Anonymous  Aug 26, 2008 
Printed Page 712
the cross_loop() function

1 def cross_loop( *sequences ) :
2 # from _Python Cookbook_, 2e pg 712
3 if sequences :
4 for x in sequences[0] :
5 for y in cross_loop( *sequences[1:] ) :
6 yield (x,) + y
7 else :
8 yield ()

I added the "*" to the cross_loop() call in line 5. Otherwise, I think, the bare
sequences[1:] would pass the slice into the recursive call to cross_loop(). The inner
calls' sequences would then be a length 1 array containing the tuples from the slice.

I'm not too sure I wasn't simply calling the function incorrectly.

def cross_product( self ) :
return cross_loop( self.y_radius_range,
self.cbcr_radius_range,
self.scale_10_range,
self.scale_15_range,
self.scale_20_range,
self.output_scale_range )

All those "_range" members are tuples of integers.

An eventual simplification was:
def cross_product( self ) :
sequences = []
for f in self.iterable_field_names :
sequences.append( getattr( self, f+"_range" ) )
return cross_loop( *sequences )

Both of those functions worked when I added the "*" to the front of the sequences[1:]
slice in the recursive call.

Anonymous