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.
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 |
|
|