Errata

Python in a Nutshell

Errata for Python in a Nutshell, Second Edition

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. If the error was corrected in a later version or reprint the date of the correction will be displayed in the column titled "Date Corrected".

The following errata were submitted by our customers and approved as valid errors by the author or editor.

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

Version Location Description Submitted By Date submitted Date corrected
Printed
Page xi
Last paragraph

Missing word: "...how **TO** use "cookies" to deal with..."

Note from the Author or Editor:
In the last paragraph of p. xi 4th line from the bottom change the text

and how use "cookies" to deal

into

and how to use "cookies" to deal

Anonymous    Jul 01, 2011
Printed
Page xi
Last paragraph

Missing word: "...how **TO** use "cookies" to deal with..."

AM: reader's right, s/how use/how to use/

Anonymous    Jul 01, 2008
Other Digital Version
xi
Last paragraph

Missing word: "...how **TO** use "cookies" to deal with..."

AM: reader's right, s/how use/how to use/

Anonymous    Jul 01, 2008
Printed
Page 4
4th paragraph

If you find you are [MORE???] productive with Java or C# than with C or Fortran...

Note from the Author or Editor:
In the 4th paragraph of p. 4, 3 lines up from the end of the paragraph, change the text

find you are productive with Java

to

find you are more productive with Java

Anonymous    Jul 01, 2011
Printed
Page 4
4th paragraph

If you find you are [MORE???] productive with Java or C# than with C or Fortran...

AM: reader's right, s/productive/more productive/

Anonymous    Jul 01, 2008
Other Digital Version
4
4th paragraph

If you find you are [MORE???] productive with Java or C# than with C or Fortran...

AM: reader's right, s/productive/more productive/

Anonymous    Jul 01, 2008
Printed
Page 43
1st paragraph of "Sets" section.

"Python 2.4 introduces two built-in set types, set and frozenset, to represent arbitrarily ordered collections..."

Actually, they're unordered as is stated in the last sentence of the following paragraph: "Sets and frozensets are not ordered."

I expect this is actually just a typo but I've flagged it as a technical mistake as the resulting text makes sense, is not right and could mislead.

Note from the Author or Editor:
In the 2nd line of the 1st para under Sets, change "arbitrary ordered collections" to "arbitrary unordered collections".

Ed Davies  Oct 14, 2009  Jul 01, 2011
Printed
Page 49
3rd paragraph

The sentence "For example, x=x+y does not modify the object to which name x was
originally bound" is incorrect, I think. Suppose x and y belong to a user-defined
class in which __add__ has been defined. Suppose __add__(self, other)

changes some

attribute (say 'value') of self. Suppose we make the statements:

z=x

x = x+y

print z.value

The point of the discussion in the book is that x is reassigned, not changed in
place. However, the object originally bound to x will be changed in
place, and that change can be seen here in z.
The introduction of a custom __add__ is not so out of left field here, since
the book is contrasting the situation to when the object has a custom __iadd__.

AM: substitute /For example, x=x+y/For example, the assignment in x=x+y/ .

Anonymous    Jul 01, 2008
Other Digital Version
49
3rd paragraph

The sentence "For example, x=x+y does not modify the object to which name x was
originally bound" is incorrect, I think. Suppose x and y belong to a user-defined
class in which __add__ has been defined. Suppose __add__(self, other)

changes some

attribute (say 'value') of self. Suppose we make the statements:

z=x

x = x+y

print z.value

The point of the discussion in the book is that x is reassigned, not changed in
place. However, the object originally bound to x will be changed in
place, and that change can be seen here in z.
The introduction of a custom __add__ is not so out of left field here, since
the book is contrasting the situation to when the object has a custom __iadd__.

AM: substitute /For example, x=x+y/For example, the assignment in x=x+y/ .

Anonymous    Jul 01, 2008
Printed
Page 80
paragraph 4, 6

RecursionLimitExceeded is not a standard exception. A RuntimeError with the message
"maximum recursion depth exceeded" is raised instead.

Note from the Author or Editor:
Throughout p.80, change mentions of RecursionLimitExceeded to RuntimeError

Anonymous   
Printed
Page 80
paragraph 4, 6

RecursionLimitExceeded is not a standard exception. A RuntimeError

with the message

"maximum recursion depth exceeded" is raised instead.

AM: reader's right; s/RecursionLimitExceeded exceptions/"maximum
recursion depth exceeded" exceptions/

Anonymous    Jul 01, 2008
Other Digital Version
80
paragraph 4, 6

RecursionLimitExceeded is not a standard exception. A RuntimeError

with the message

"maximum recursion depth exceeded" is raised instead.

AM: reader's right; s/RecursionLimitExceeded exceptions/"maximum
recursion depth exceeded" exceptions/

Anonymous    Jul 01, 2008
Printed
Page 84
Attributes of class objects

Hello,


At the beginning of the paragraph, there is:

#-----------------
class C1(object):
x = 23
#-----------------

It's OK, but and after in the same page there is:

#-----------------
C1.__dict__['z'] = 67
#-----------------

With Python 2.5, this code is false. If I test with my computer, I have this error :

#-----------------
>>> class C1(object):
... x = 23
...
>>> C1.__dict__['z'] = 67
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'dictproxy' object does not support item assignment
#-----------------

Thanks a lot.


Fran?ois

Note from the Author or Editor:
In the 6th paragraph of text in the page (starting with "There is no difference"), add at the end of the paragraph the sentence (parenthesis included)

"(In Python 2.5, assignment to entries in the __dict__ of a new-style class raises an exception)"

Anonymous  Aug 18, 2008  Jul 01, 2011
Printed
Page 87
Attributes of instance objects paragraph

Class C7 is an old-style class. The author always used new style ones
in the first part of the chapter.

AM: The slight style variation can be fixed by s/class C7: pass/class C7(object):
pass/

Anonymous    Jul 01, 2008
Other Digital Version
87
Attributes of instance objects paragraph

Class C7 is an old-style class. The author always used new style ones
in the first part of the chapter.

AM: The slight style variation can be fixed by s/class C7: pass/class C7(object):
pass/

Anonymous    Jul 01, 2008
Printed
Page 94
Code block at bottom of page

For this code block to be illustrative of the distinction between legacy- and new-style resolution order and to be consonant with the phrase '...for the case of this kind of "diamond-shaped" inheritance graph' in the second paragraph on the following page class Base3, like Base2, should derive from Base1.

With Base3 not deriving from Base1 the code prints "Base1" even if it is modified to be new-style (by deriving Base1 from object).

Note from the Author or Editor:
change the 4th line of the code block from the current

class Base3:

to

class Base3(Base1):

Ed Davies  Oct 19, 2009  Jul 01, 2011
Printed
Page 99
6th paragraph, Static Methods

In the discussion of static methods, the book says:

A static method may have any signature: it may have no arguments, and the first argument, if any, plays no
special role.

The first part of the sentence contradicts the rest of it. It should probably read:

it may have *any* arguments, and the first argument, if any, plays no special role.

I tested it with python 2.4.4, and a static method can have any number of arguments.

This refers to 8/05 edition of the book, but I didn't see this error mentioned in the errata list of any
of the subsequent editions.

Note from the Author or Editor:
(NOT on p. 82 but on p. 99, first paragraph under Static methods 4th line) change the phrase "it may have no parameters, and the first parameter, if any, plays" to "it might have no parameters, and the first parameter, if it does have any, plays"

Anonymous    Jul 01, 2011
Printed
Page 107
__hash__, 3rd paragraph

Book says: "When __hash__ is absent, but __cmp__ or __eq__ is present, hash(x), and the use of x as a dictionary key, raise an exception."

This is confusing because in new-style classes, the __hash__ inherited from object doesn't throw an exception even if __cmp__ or __eq__ is defined and __hash__ is not overridden.

Note from the Author or Editor:
Add at the end of the 3rd paragraph (after "a dictionary key.") the following sentencse:

Note that `__hash__` "is present" even when it's not coded directly in the object's class but inherited from a base class. For example, a new-style class which subclasses `object` inherits a __hash__ which unconditionally calls `id`.

Tomek Czajka  Dec 10, 2009  Jul 01, 2011
Printed
Page 110
Example at bottom of page

In the __getitem__ example, self.indices should be index.indices; also, one
parenthesis seems to be missing at the end.

Note from the Author or Editor:
change the penultimate line of code at the bottom of p. 100 which now reads

for x in xrange(*self.indices(len(self)))

to read


for x in xrange(*index.indices(len(self))))

i.e. change self to index and add one closed paren to the end for a total of 4 closed parentheses while it now has only 3.

Anonymous    Jul 01, 2011
Printed
Page 110
Example at bottom of page

In the __getitem__ example, self.indices should be index.indices; also, one
parenthesis seems to be missing at the end.

AM: reader's right on both accounts, s/self.indices/index.indices/ AND
add a ) at the end of that same line

Anonymous    Jul 01, 2008
Other Digital Version
110
Example at bottom of page

In the __getitem__ example, self.indices should be index.indices; also, one
parenthesis seems to be missing at the end.

AM: reader's right on both accounts, s/self.indices/index.indices/ AND
add a ) at the end of that same line

Anonymous    Jul 01, 2008
Printed
Page 165
In 'ord' section

The integer code returned for unicode is [0,65534], but shouldn't it be 65535? But
if it cannot return 65535, I would have appreciated knowing why it wouldn't.

Note from the Author or Editor:
on p. 165 under `ord` change the number 65534 to 65535

Anonymous    Jul 01, 2011
Printed
Page 165
In 'ord' section

The integer code returned for unicode is [0,65534], but shouldn't it
be 65535? But if it cannot return 65535, I would have appreciated knowing why it wouldn't.

AM: reader's right, s/65534/65535/

Anonymous    Jul 01, 2008
Other Digital Version
165
In 'ord' section

The integer code returned for unicode is [0,65534], but shouldn't it
be 65535? But if it cannot return 65535, I would have appreciated knowing why it wouldn't.

AM: reader's right, s/65534/65535/

Anonymous    Jul 01, 2008
Printed
Page 166
End of 'reduce' section

result of reduce() is the product of a sequence of numbers, but it is getting bound
to 'thesum'.

Note from the Author or Editor:
on p. 166, last line under `reduce`, change `thesum` to `theprod`

Anonymous    Jul 01, 2011
Printed
Page 166
End of 'reduce' section

result of reduce() is the product of a sequence of numbers, but it is getting bound to 'thesum'.

AM: reader's right, to reduce confusion s/thesum/theprod/

Anonymous    Jul 01, 2008
Other Digital Version
166
End of 'reduce' section

result of reduce() is the product of a sequence of numbers, but it is getting bound to 'thesum'.

AM: reader's right, to reduce confusion s/thesum/theprod/

Anonymous    Jul 01, 2008
Printed
Page 175
2nd paragraph

>>> import collections, operator
>>> def sorted_histograms(seq):
d = collections.defaultdict(int)
for item in seq: d[item] += 1
print d
return sorted(d.iteritems, key=operator.itemgetter(1), reverse=True)

>>> a = [ "b", "c", "d", "b", "c", "c", "e", "d"]
>>> b = sorted_histograms(a)
defaultdict(<type 'int'>, {'c': 3, 'b': 2, 'e': 1, 'd': 2})

Traceback (most recent call last):
File "<pyshell#4>", line 1, in <module>
b = sorted_histograms(a)
File "<pyshell#2>", line 9, in sorted_histograms
return sorted(d.iteritems, key=operator.itemgetter(1), reverse=True)
TypeError: 'builtin_function_or_method' object is not iterable
>>> b

Traceback (most recent call last):
File "<pyshell#5>", line 1, in <module>
b
NameError: name 'b' is not defined

Note from the Author or Editor:
on p. 175, in the first code snippet, change the start of the code line that now reads

return sorted(d.iteritems, key=operator

to read instead

return sorted(d.iteritems(), key=operator

i.e. add an open and a closed paren just before the first comma (the rest of the line must remain unchanged).

Anonymous    Jul 01, 2011
Printed
Page 175
2nd paragraph

>>> import collections, operator

>>> def sorted_histograms(seq):

d = collections.defaultdict(int)

for item in seq: d[item] += 1

print d

return sorted(d.iteritems, key=operator.itemgetter(1), reverse=True)

>>> a = [ "b", "c", "d", "b", "c", "c", "e", "d"]

>>> b = sorted_histograms(a)

defaultdict(<type 'int'>, {'c': 3, 'b': 2, 'e': 1, 'd': 2})

Traceback (most recent call last):

File "<pyshell#4>", line 1, in <module>

b = sorted_histograms(a)

File "<pyshell#2>", line 9, in sorted_histograms

return sorted(d.iteritems, key=operator.itemgetter(1), reverse=True)

TypeError: 'builtin_function_or_method' object is not iterable

>>> b

Traceback (most recent call last):

File "<pyshell#5>", line 1, in <module>

b

NameError: name 'b' is not defined

AM: reader's right, s/sorted(d.iteritems, /sorted(d.iteritems(), /

Anonymous    Jul 01, 2008
Other Digital Version
175
2nd paragraph

>>> import collections, operator

>>> def sorted_histograms(seq):

d = collections.defaultdict(int)

for item in seq: d[item] += 1

print d

return sorted(d.iteritems, key=operator.itemgetter(1), reverse=True)

>>> a = [ "b", "c", "d", "b", "c", "c", "e", "d"]

>>> b = sorted_histograms(a)

defaultdict(<type 'int'>, {'c': 3, 'b': 2, 'e': 1, 'd': 2})

Traceback (most recent call last):

File "<pyshell#4>", line 1, in <module>

b = sorted_histograms(a)

File "<pyshell#2>", line 9, in sorted_histograms

return sorted(d.iteritems, key=operator.itemgetter(1), reverse=True)

TypeError: 'builtin_function_or_method' object is not iterable

>>> b

Traceback (most recent call last):

File "<pyshell#5>", line 1, in <module>

b

NameError: name 'b' is not defined

AM: reader's right, s/sorted(d.iteritems, /sorted(d.iteritems(), /

Anonymous    Jul 01, 2008
Printed
Page 177
Description of heappop

Doesn't heappop run in O(log(len(alist))) time instead of O(len(alist))? If it was
O(len(alist)), then heapsort would be O(n^2).

Note from the Author or Editor:
p. 177 last line under heappop, change the text

runs in O(len(alist)) time

to

runs in O(log(len(alist))) time

Anonymous    Jul 01, 2011
Printed
Page 177
Description of heappop

Doesn't heappop run in O(log(len(alist))) time instead of

O(len(alist))? If it was

O(len(alist)), then heapsort would be O(n^2).

AM: reader's right, s/O(len(alist))/O(log(len(alist)))/

Anonymous    Jul 01, 2008
Other Digital Version
177
Description of heappop

Doesn't heappop run in O(log(len(alist))) time instead of

O(len(alist))? If it was

O(len(alist)), then heapsort would be O(n^2).

AM: reader's right, s/O(len(alist))/O(log(len(alist)))/

Anonymous    Jul 01, 2008
Printed
Page 183
Third attribute description, "cycle"

Syntax summary is "count(iterable)", should be "cycle(iterable)"

Note from the Author or Editor:
on p. 183 on the first line of the block for `cycle`, change `count` to `cycle`

Anonymous    Jul 01, 2011
Printed
Page 183
Third attribute description, "cycle"

Syntax summary is "count(iterable)", should be "cycle(iterable)"

AM: reader's right, s/count/cycle/

Anonymous    Jul 01, 2008
Other Digital Version
183
Third attribute description, "cycle"

Syntax summary is "count(iterable)", should be "cycle(iterable)"

AM: reader's right, s/count/cycle/

Anonymous    Jul 01, 2008
Printed
Page 187
3rd section

The string method 'decode' which was introduced in Python 2.2 is missing.

http://docs.python.org/lib/string-methods.html

AM: reader's right. Just before 'encode' where it alphabetically belongs, with s/encode/decode/ in
the syntax summary as well, and short description

Returns a (typically unicode) string obtained from s with the given coded and error
handling. See "Unicode" on page 198 for more details.

i.e. basically the same as encode except for the parenthetical note
that the result is typically Unicode. Maybe the apparent duplication
is what caused the snip...?

Anonymous    Jul 01, 2008
Other Digital Version
187
3rd section

The string method 'decode' which was introduced in Python 2.2 is missing.

http://docs.python.org/lib/string-methods.html

AM: reader's right. Just before 'encode' where it alphabetically belongs, with s/encode/decode/ in
the syntax summary as well, and short description

Returns a (typically unicode) string obtained from s with the given coded and error
handling. See "Unicode" on page 198 for more details.

i.e. basically the same as encode except for the parenthetical note
that the result is typically Unicode. Maybe the apparent duplication
is what caused the snip...?

Anonymous    Jul 01, 2008
Printed
Page 189
Description of rstrip

Text reads "Returns a copy of s, removing leading characters that are found in string x"
but should read "trailing" instead of "leading".

Note from the Author or Editor:
on p. 189, under `rstrip` replace the word
leading
with
trailing

Anonymous    Jul 01, 2011
Printed
Page 189
Description of rstrip

Text reads "Returns a copy of s, removing leading characters that are found in string x"
but should read "trailing" instead of "leading".

AM: reader's right, s/leading/trailing/

Anonymous    Jul 01, 2008
Other Digital Version
189
Description of rstrip

Text reads "Returns a copy of s, removing leading characters that are found in string x"
but should read "trailing" instead of "leading".

AM: reader's right, s/leading/trailing/

Anonymous    Jul 01, 2008
Printed
Page 197
3rd paragraph (if we count the examples as a paragraph)

It explains "textwrap.fill". It says that...
"""
Returns a single multiline string that is exactly equal to '
'.join(fill(s,width)).
"""
... and it should say ...
"""
Returns a single multiline string that is exactly equal to '
'.join(wrap(s,width)).
"""

Note from the Author or Editor:
p. 197 under `fill`, replace the code

join(fill(s, width))

to be

join(wrap(s, width))

Anonymous    Jul 01, 2011
Printed
Page 197
3rd paragraph (if we count the examples as a paragraph)

It explains "textwrap.fill". It says that...

"""

Returns a single multiline string that is exactly equal to

'
'.join(fill(s,width)).

"""

... and it should say ...

"""

Returns a single multiline string that is exactly equal to

'
'.join(wrap(s,width)).

"""

AM: Reader's right, s/fill/wrap/

Anonymous    Jul 01, 2008
Other Digital Version
197
3rd paragraph (if we count the examples as a paragraph)

It explains "textwrap.fill". It says that...

"""

Returns a single multiline string that is exactly equal to

'
'.join(fill(s,width)).

"""

... and it should say ...

"""

Returns a single multiline string that is exactly equal to

'
'.join(wrap(s,width)).

"""

AM: Reader's right, s/fill/wrap/

Anonymous    Jul 01, 2008
Printed
Page 198
The repr module

Should refer to page 166, not 198.

Also index on page 691 should reference page 166 under repr (in addition to 198)

Anonymous    Sep 01, 2007
Printed
Page 203
4th paragraph

It says "rE", it should say "RE".

Anonymous    Sep 01, 2007
Printed
Page 207
first code snippet

The third line of code is wrapping down, it must not.

Note from the Author or Editor:
on p. 207, first code example, the 3rd line is too long to print as a single line. Change it into two lines by breaking at the colon and indenting the rest 4 spaces more, i.e

if digatend.search(open('afile.txt').read()):
print "some lines end with digits"

the rest of the snippet must remain unchanged

Anonymous    Jul 01, 2011
Printed
Page 207
first code snippet

The third line of code is wrapping down, it must not.

AM: reader's right, break the line typographically right after the
colon ':' and put 'print' etc on the NEXT typographical line indented four spaces

Anonymous    Jul 01, 2008
Other Digital Version
207
first code snippet

The third line of code is wrapping down, it must not.

AM: reader's right, break the line typographically right after the
colon ':' and put 'print' etc on the NEXT typographical line indented four spaces

Anonymous    Jul 01, 2008
Printed
Page 231
first code snippet

The third line of code is wrapping down, it must not.

AM: reader's right, put a at the end of the third line and indent the following
(fourth) line four spaces

Anonymous    Jul 01, 2008
Other Digital Version
231
first code snippet

The third line of code is wrapping down, it must not.

AM: reader's right, put a at the end of the third line and indent the following
(fourth) line four spaces

Anonymous    Jul 01, 2008
Printed
Page 307
strftime

fmt parameter is missing in function prototype.

Note from the Author or Editor:
p. 307 at the end first line of `strftime`, change the existing

d.strftime()

to be instead

d.strftime(fmt)

Anonymous    Jul 01, 2011
Printed
Page 307
strftime

fmt parameter is missing in function prototype.

AM: reader's right, s/d.strftime()/d.strftime(fmt)/

Anonymous    Jul 01, 2008
Other Digital Version
307
strftime

fmt parameter is missing in function prototype.

AM: reader's right, s/d.strftime()/d.strftime(fmt)/

Anonymous    Jul 01, 2008
Printed
Page 310
5th method description

The method name, in the syntax description, says "d.timezone(tz)", it should say "d.astimezone(tz)".

Note from the Author or Editor:
on p. 310 under `astimezone`, change

d.timezone(tz)

to

d.astimezone(tz)

Anonymous    Jul 01, 2011
Printed
Page 310
Middle of page, description of utcnow method.

Final paragraph of description of utcnow method (starting "Instances of class datetime support...") is general description which should, I think, be on page 309 at the end of the introduction to the datetime class (after the paragraph ending "...and an optional tzinfo (None for na?ve instances).").

Note from the Author or Editor:
move the six lines on p.310 from "Instances if class datetime support some arithmetic:" all the way to "both aware or both naive" to become a separate paragraph on p.309 right after the only paragraph of text now there (which ends with "(None for naive instances)".

The other two lines of the same paragraph in p. 310 (from "An instance d" to "following methods" must stay on p. 310 but must be aligned flush left, NOT indented as they are now.

Ed Davies  Mar 08, 2010  Jul 01, 2011
Printed
Page 310
5th method description

The method name, in the syntax description, says "d.timezone(tz)", it should say "d.astimezone(tz)".

AM: reader's right, s/timezone/astimezone/

Anonymous    Jul 01, 2008
Other Digital Version
310
5th method description

The method name, in the syntax description, says "d.timezone(tz)", it should say "d.astimezone(tz)".

AM: reader's right, s/timezone/astimezone/

Anonymous    Jul 01, 2008
Printed
Page 311
strftime

fmt argument missing from prototype.

Note from the Author or Editor:
on p. 311 under `strftime` change d.strftime() to d.strftime(fmt)

Anonymous    Jul 01, 2011
Printed
Page 311
strftime

fmt argument missing from prototype.

AM: reader's right, s/d.strftime()/d.strftime(fmt)/

Anonymous    Jul 01, 2008
Other Digital Version
311
strftime

fmt argument missing from prototype.

AM: reader's right, s/d.strftime()/d.strftime(fmt)/

Anonymous    Jul 01, 2008
Printed
Page 312
example usage for timedelta

The second timedelta() call in the "print repr(timedelta...)" examples should be
changed from
timedelta(minutes=0.5)
to
timedelta(hours=-1)

for the example output to be correct.

Note from the Author or Editor:
on p.312 in the example under `timedelta` change the *SECOND* occurrence (only! leave the first one unchanged!) from

minutes=0.5

to

hours=-1

the rest of the code before, around and after that change must remain unchanged.

Anonymous    Jul 01, 2011
Printed
Page 312
example usage for timedelta

The second timedelta() call in the "print repr(timedelta...)" examples should be

changed from

timedelta(minutes=0.5)

to

timedelta(hours=-1)

for the example output to be correct.

AM: reader's right, s/minutes=0.5/hours=-1/ in that second example.

Anonymous    Jul 01, 2008
Other Digital Version
312
example usage for timedelta

The second timedelta() call in the "print repr(timedelta...)" examples should be

changed from

timedelta(minutes=0.5)

to

timedelta(hours=-1)

for the example output to be correct.

AM: reader's right, s/minutes=0.5/hours=-1/ in that second example.

Anonymous    Jul 01, 2008
Printed
Page 350
Bottom, and next 2 pages (not fixed by errata)

I don't know how critical exception handling is to the content of your code samples. A lot of books state up-front that they've done a minimal job in this regard, but I didn't see such a disclaimer in this book. I would have marked this as a "Serious technical mistake" except for this fact. It certainly could be serious for anyone who naively uses this in production code.

You present the ExternalInterfacing, Serializer, and Worker classes in the book (and to a lesser degree in the errata). But note what happens if the thread run() method encounters an exception by calling self.externalCallable. I believe the ExternalInterfacing/Serializer/Worker thread will terminate, and the thread calling request()/apply(), which is blocking by calling q.get(), will deadlock (assuming it keeps running at all, as http://docs.python.org/lib/module-thread.html suggests for the earlier thread module).

Note that the Worker thread may terminate but since it posts results asynchronously, this doesn't necessarily cause an actual deadlock. I don't see this addressed in the errata so I wanted to mention it.

My suggestion is to catch exceptions in run(), return them in lieu of results, detect exceptions in request()/apply(), and raise them when they occur. Raising isn't really possible for the Worker, but the exception could at least be put into the result queue.

Note from the Author or Editor:
Add in the front matter of the book a disclaimer: "the example code in this book is intended to provide concise examples, and therefore often does not deal with possible errors and anomalies with the rock-solidity required in production code".

Anonymous  Sep 22, 2008 
Printed
Page 350, 351
Code example starting at the bottom

'Threading.Thread' should be 'threading.Thread' in this and the next few code fragments.

Note from the Author or Editor:
Change the leading T (only) from uppercase to lowercase throughout the code on p.350 and 351 so all mentions of "Threading.Thread" become "threading.Thread"

Dave Smith  Feb 13, 2011  Jul 01, 2011
Printed
Page 351
Top code snippet

The example contains a subtle error whereby a thread requesting work will occasionally get a different thread's result.

The issue is that Queue's get() (which uses a Condition wrapping a Lock) makes no guarantee about which waiting thread will get unblocked.

The problem can be demonstrated using the example code and 100 threads each making 100 requests, with a random delay between requests and a random delay in the externalCallable. Requesting threads would get the wrong answer about 0.05-0.1% of the time. Lower the thread count, and the problem diminishes to the point (and <10 threads) that it's downright rare.

(Python 2.6.5, Ubuntu 10.04.2)

Note from the Author or Editor:
on p.351, change the first block of code (from the start of the page, leave the lines on p. 350 alone as they're just fine) to:

self.externalCallable = externalCallable
self.workRequestQueue = Queue.Queue()
self.start()
def request(self, *args, **kwds):
"called by other threads as externalCallable would be"
q = Queue.Queue()
self.workRequestQueue.put((q, args, kwds))
return q.get()
def run(self):
while 1:
q, args, kwds = self.workRequestQueue.get()
q.put(self.externalCallable(*args, **kwds))

and the second block of code (after the first 5 lines that are the same as the lines on p. 350 and also just fine and must remain unchanged) to::

self.workRequestQueue = Queue.Queue()
self.start()
def apply(self, callable, *args, **kwds):
"called by other threads as callable would be"
q = Queue.Queue()
self.workRequestQueue.put((q, callable, args, kwds))
return q.get()
def run(self):
while 1:
q, callable, args, kwds = self.workRequestQueue.get()
q.put(callable(*args, **kwds))

Dave Smith  Feb 13, 2011  Jul 01, 2011
Printed
Page 448
Events example

it uses both "Import Tkinter" and "from Tkinter import *".
The first is unnecessary and would be incorrect if the other was removed.

Note from the Author or Editor:
in p. 449 in the code example remove the first line which now reads

import Tkinter

Anonymous    Jul 01, 2011
Printed
Page 458
2nd paragraph under Example 18-2

method 'testExactly1Argument' referred to in paragraph is actually testExactlyOneArgument in Example 18-2

Note from the Author or Editor:
p 458 example 18-2 change the code that now reads

def testExactlyOneArgument(self):

to read instead

def testExactly1Argument(self):

Anonymous    Jul 01, 2011
Printed
Page 458
Bottom of Example 18-2

space between equal signs:

if __name__= ='__main__':
should be:
if __name__=='__main__':

Anonymous    Sep 01, 2007
Printed
Page 458
2nd paragraph under Example 18-2

method 'testExactly1Argument' referred to in paragraph is actually
testExactlyOneArgument in Example 18-2

AM: reader's right, s/testExactly1Argument/testExactlyOneArgument/ in that text

Anonymous    Jul 01, 2008
Other Digital Version
458
2nd paragraph under Example 18-2

method 'testExactly1Argument' referred to in paragraph is actually
testExactlyOneArgument in Example 18-2

AM: reader's right, s/testExactly1Argument/testExactlyOneArgument/ in that text

Anonymous    Jul 01, 2008
Printed
Page 485
First two paragraphs

The example in this section was how to quickly sort a list of strings based on the second word in each
string. The operator.itemgetter technique incorrectly sorts based on the second character in each string,
not the second word.

Maybe use something like:

L.sort(key=lambda x: x.split()[1])

Note from the Author or Editor:
p. 486, first code snippet, change both lines of code to read instead

def secondword(a): return a.split(1)
L.sort(key=secondword)

Anonymous    Jul 01, 2011
Printed
Page 485
Last code section

The example in this section was how to quickly sort a list of strings based on the second word in
each string. The operator.itemgetter technique incorrectly sorts based on the second character in
each string, not the second word.

Maybe use something like:

L.sort(key=lambda x: x.split()[1])

AM: reader's right that the code at the almost-bottom of p.485 is incorrect, but the right fix
is to change those two lines into the following two lines instead:

def secondword(s): return s.split()[1]

L.sort(key=secondword)

Anonymous    Jul 01, 2008
Other Digital Version
485
Last code section

The example in this section was how to quickly sort a list of strings based on the second word in
each string. The operator.itemgetter technique incorrectly sorts based on the second character in
each string, not the second word.

Maybe use something like:

L.sort(key=lambda x: x.split()[1])

AM: reader's right that the code at the almost-bottom of p.485 is incorrect, but the right fix
is to change those two lines into the following two lines instead:

def secondword(s): return s.split()[1]

L.sort(key=secondword)

Anonymous    Jul 01, 2008
Printed
Page 511
1st paragraph after "Network News" title

It talks about POP protocol, and should talk about NNTP protocol.

Note from the Author or Editor:
2nd line of the paragraph under Network News, change the text that now read

The specifications of the POP protocol

to be

The specifications of the NNTP protocol

Anonymous    Jul 01, 2011
Printed
Page 511
1st paragraph after "Network News" title

It talks about POP protocol, and should talk about NNTP protocol.

AM: reader's right, s/POP/NNTP/

Anonymous    Jul 01, 2008
Other Digital Version
511
1st paragraph after "Network News" title

It talks about POP protocol, and should talk about NNTP protocol.

AM: reader's right, s/POP/NNTP/

Anonymous    Jul 01, 2008
Printed
Page 518
Bottom of page

Example program produces error message:

"Traceback (most recent call last):

File "C:xmlrpctest.py", line 6, in <module>

results = proxy.meerkat.getItems({'search':'Python', 'num_items':7})

File "C:Python25Libxmlrpclib.py", line 1147, in __call__

return self.__send(self.__name, args)

File "C:Python25Libxmlrpclib.py", line 1437, in __request

verbose=self.__verbose

File "C:Python25Libxmlrpclib.py", line 1191, in request

headers

ProtocolError: <ProtocolError for

www.oreillynet.com/meerkat/xml-rpc/server.php: 301 Moved Permanently>"

AM: reader's right, Meerkat is no longer available and was shut down March 2, 2006. Delete example.

Anonymous    Jul 01, 2008
Other Digital Version
518
Bottom of page

Example program produces error message:

"Traceback (most recent call last):

File "C:xmlrpctest.py", line 6, in <module>

results = proxy.meerkat.getItems({'search':'Python', 'num_items':7})

File "C:Python25Libxmlrpclib.py", line 1147, in __call__

return self.__send(self.__name, args)

File "C:Python25Libxmlrpclib.py", line 1437, in __request

verbose=self.__verbose

File "C:Python25Libxmlrpclib.py", line 1191, in request

headers

ProtocolError: <ProtocolError for

www.oreillynet.com/meerkat/xml-rpc/server.php: 301 Moved Permanently>"

AM: reader's right, Meerkat is no longer available and was shut down March 2, 2006. Delete example.

Anonymous    Jul 01, 2008
Printed
Page 524
Middle of page, End of 3rd paragraph

getsockopt example reads:
import socket
s = socket.socket()
print s.getsockopt(s.SOL_SOCKET, s.S0_REUSEADDR)

Code should read:
import socket
s = socket.socket()
print s.getsockopt(socket.SOL_SOCKET, socket.S0_REUSEADDR)

Note from the Author or Editor:
p. 524 in the code example change the one line that now reads

print s.getsockopt(s.SOL_SOCKET, s.SO_REUSEADDR)

to read instead

print s.getsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR)

the rest of the code in the example must remain unchanged.

Anonymous    Jul 01, 2011
Printed
Page 524
Middle of page, End of 3rd paragraph

getsockopt example reads:

import socket

s = socket.socket()

print s.getsockopt(s.SOL_SOCKET, s.S0_REUSEADDR)

Code should read:

import socket

s = socket.socket()

print s.getsockopt(socket.SOL_SOCKET, socket.S0_REUSEADDR)

AM: Reader's right, pls change as he's indicated (except it's SO_REUSEADDR as in the book, not
S0_REUSEADDR as he indicates -- an uppercase O, *not* a zero digit).

Anonymous    Jul 01, 2008
Other Digital Version
524
Middle of page, End of 3rd paragraph

getsockopt example reads:

import socket

s = socket.socket()

print s.getsockopt(s.SOL_SOCKET, s.S0_REUSEADDR)

Code should read:

import socket

s = socket.socket()

print s.getsockopt(socket.SOL_SOCKET, socket.S0_REUSEADDR)

AM: Reader's right, pls change as he's indicated (except it's SO_REUSEADDR as in the book, not
S0_REUSEADDR as he indicates -- an uppercase O, *not* a zero digit).

Anonymous    Jul 01, 2008
Printed
Page 541
3rd reactor method description, connectTCP

The syntax description says "r.listenTCP(", should be "r.connectTCP("

Note from the Author or Editor:
p.541 first line starting `connectTCP`, change the start of the syntax summary from the current `r.listenTCP` to `r.connectTCP` (the rest of the syntax summary must remain unchanged).

Anonymous    Jul 01, 2011
Printed
Page 541
3rd reactor method description, connectTCP

The syntax description says "r.listenTCP(", should be "r.connectTCP("

AM: Reader's right, s/listenTCP/connectTCP/

Anonymous    Jul 01, 2008
Other Digital Version
541
3rd reactor method description, connectTCP

The syntax description says "r.listenTCP(", should be "r.connectTCP("

AM: Reader's right, s/listenTCP/connectTCP/

Anonymous    Jul 01, 2008
Printed
Page 664
2

Using jythonc (jython version 2.2.1):
If you want to see a jython class from java you need to extend a parent java class. So

class APythonClass:
...
must be

class APythonClass(java.lang.object):
...

Jython 2.5rc2 doesn't use jythonc (http://www.jython.org/Project/jythonc.html).

Note from the Author or Editor:
The reader is correct: please change `class APythonClass:` to `class APythonClass(java.lang.object):`. The book does NOT cover versions 2.5 and later so the remark about 2.5rc2 may be omitted.

Maurizio Lupo  May 27, 2009  Jul 01, 2011
Printed
Page 693
sys module main entry in index

There is no page number next to the listing. There should be a reference
to page 168, which is where the main discussion of the sys module begins.

Anonymous    Sep 01, 2007
Printed
Page 695
lower right quadrant

The index refers the reader to page 76 for information on 'yield'. There is no useful information on yield
on that page, but there is on page 78.

Note from the Author or Editor:
p. 695 (index) under Y, it points yield to page 76: change the index entry to point to p. 78 instead

Anonymous