PYTHON ESSENTIAL REFERENCE - ERRATA

Python Essential Reference, 4th Edition [Amazon]
Addison-Wesley Professional (July 19, 2009)
ISBN 0672329786; 717 pages

Official Errata Page

This page describes all of the typos and corrections for the Python Essential Reference, 4th Edition. If you find errors not listed here, please let me know so that I can make future editions better!

Special thanks to the following contributors for their "eagle eyes":

Locations are specified by page and paragraph numbers (counting from the top of the page). Errors are denoted in red. Additions or corrections are denoted in blue.

Location Description

pg 7, ¶1

"On UNIX, EOF is Ctrl-D; on Windows, it's Ctrl-Z."

Should be

"On UNIX, EOF is Ctrl-D; on Windows, it's Ctrl-Z (or F6)."

pg 9, Note midpage.

"... If you do this, the normal indentation rules don't apply to the next line, so you are free to format the continued lines as you wish."

Should be

"... If you do this, the normal indentation rules don't apply to the next line, so you are free to format the continued lines as you wish. A backslash is never needed for code enclosed in ( ), [ ], or { }."

pg 13, Listing 1.2

Missing colon in code example.

import sys                   # Load the sys module
if len(sys.argv) != 2        # Check number of command line arguments
   ...

Should be:

import sys                   # Load the sys module
if len(sys.argv) != 2:       # Check number of command line arguments
   ...

pg 21, ¶1 code

Inconsistent indentation in code example at top of page.

...
# Feed an active log file into all matchers.  Note for this to work,
   # a web server must be actively writing data to the log

Should be:

...
# Feed an active log file into all matchers.  Note for this to work,
# a web server must be actively writing data to the log

pg 27, ¶1

"To specify an integer using octal, hexadecimal, or binary notation, precede the value with 0, 0x, or 0b respectively (for example, 0644, 0x100fea8, or 0b11101010)."

Should be

"To specify an integer using octal, hexadecimal, or binary notation, precede the value with 0o, 0x, or 0b respectively (for example, 0o644, 0x100fea8, or 0b11101010)."

Note: 0o is the number zero followed by a lowercase letter O.

pg 36, code at bottom

Missing comma and inconsistent use of quotation marks in dictionary.

items = {
    'number' : 42
    'text' : "Hello World"
}

Should be:

items = {
    'number' : 42,
    'text' : 'Hello World'
}

pg 40, ¶2

Clarification of sorting requirements.

"The s.sort() method sorts the elements of a list and optionally accepts a key function and reverse flag, both of which must be specified as keyword arguments."

Should be

"The s.sort() method sorts the elements of a list (all of which should be of a uniform type) and optionally accepts a key function and reverse flag, both of which must be specified as keyword arguments."

pg 41, table 3.4

Clarification of sort() description.

"Sorts items of s in place. key is a key function. reverse is a flag that sorts the list in reverse order. key and reverse should always be specified as keyword arguments."

Should be

"Sorts items of s in place. key is a key function. reverse is a flag that sorts the list in reverse order. key and reverse should always be specified as keyword arguments. The items in s should all be of a uniform type.

pg 44, table 3.5

Clarification of zfill() description.

"Pads a string with zeros on the left up to the specified width.

Should be

"Pads a string with the '0' digit character on the left up to the specified width.

pg 45, table 3.6

Clarification of items() description.

"Returns a sequence of (key, value) pairs."

Should be

"Returns a sequence of all (key, value) pairs in m."

pg 45, table 3.6

Clarification of keys() description.

"Returns a sequence of key values."

Should be

"Returns a sequence of all key values in m."

pg 49, ¶3

"In the example, we have passed f, a an instance of Foo, ..."

Should be

"In the example, we have passed f, an instance of Foo, ..."

pg 55, code midpage

"is" should be "if".

x = A.__new__(A,args)
is isinstance(x,A): x.__init__(args)

Should be:

x = A.__new__(A,args)
if isinstance(x,A): x.__init__(args)

pg 58, ¶1

"Keep in mind that descriptions are optional and rarely need to be defined."

Should be

"Keep in mind that descriptors are optional and are rarely defined directly."

pg 58, Table 3.17

Clarify the description of __get__().

"Returns an attribute value or raises AttributeError."

Should be

"Returns the value of an attribute on instance. If instance is None, self should be returned."

pg 59, ¶3

Clarification of extended slicing

"For example, the following variations of extended slicing are all supported and might be useful for working with multidimensional data structures such as matrices and arrays:"

Should be

"For example, the following variations of extended slicing are all supported by Python's syntax and are sometimes used to manipulate multidimensional data structures such as matrices and arrays in third-party extensions such as NumPy:"

pg 60, code at top of page

Extra parens in code comment

x = _iter.next() (#_iter.__next__() in Python 3)

Should be:

x = _iter.next() # _iter.__next__() in Python 3

pg 67, table midpage

In the "Operations on Sequences" section, there is a missing comma after "v2" and the wrong font used on the "s" in this fragment:

v1, v2... , vn = s

Should be (note italics on "s"):

v1, v2, ... , vn = s

pg 68, code at bottom

Wrong result in code example:

...
d = a[0:5:2]         # d = [0,2]
...

Should be:

...
d = a[0:5:2]         # d = [0,2,4]
...

pg 69, code in bottom half page

Use of a better example that illustrates replacing the entire contents of a list:

...
a[2:] = [0]      # a = [1,6,0]
...

Should be replaced with:

...
a[:] = [7,8]     # a = [7,8].  id(a) remains the same
...

pg 72, 2nd code example

More consistent use of string formatting:

name = "Elwood"
age = 41
r = "%(name)s is %(age)s years old" % vars()

Should be:

name = "Elwood"
age = 41
r = "%(name)s is %(age)d years old" % vars()

pg 72, ¶3

Missing "*" on kwargs:

"A more advanced form of string formatting is available using the s.format(*args,*kwargs) method on strings."

Should be:

"A more advanced form of string formatting is available using the s.format(*args,**kwargs) method on strings."

pg 75, ¶5

Clarification on augmented assignment semantics:

"Augmented assignment doesn't violate mutability of perform in-place modifications of the objects. Therefore, writing x += y creates an entirely new object x with the value x + y.

Should be:

"Augmented assignment may or may not perform in-place modification of an object depending on its implementation. There, writing x + y might modify x in-place or create an entirely new object with the value x + y.

pg 76, code example midpage

Code cleanup

from functools import partial
f = partial(foo,1,2)  # Supply values to x and y arguments of foo
f(3)         # Calls foo(1,2,3), result is 6

Should be:

from functools import partial
f = partial(foo,1,2)  # Supply values to x and y arguments of foo
result = f(3)         # Calls foo(1,2,3), result is 6

pg 78, Table 4.3, bottom of page

Cleanup of comparisons:

There is an extra blank line that should be eliminated and a semicolon in place of comma:

x < y, x <= y,

x > y; x >= y,
x == y, x != y

Should be (pay careful attention to punctuation including trailing commas)

x < y, x <= y,
x > y, x >= y,
x == y, x != y,

Also, change this description:

"Comparison, identity, and sequence membership tests"

To the following:

"Value comparison, object identity, and sequence membership tests"

pg 79, Table 4.3, top of page

Missing punctuation:

x is y, x is not y
x in s, x not in s

Should be (pay careful attention to trailing comma on first line):

x is y, x is not y,
x in s, x not in s

pg 79, Code Example

Bad spacing in example:

minvalue = a if a <=b else b

Should be (pay careful attention to the extra space before b):

minvalue = a if a <= b else b

pg 85, Code example at bottom

Add a code comment with clarification:

try:
   do something
except Exception as e:
   error_log.write('An error occurred : %s\n' % e)

Should be:

try:
   do something
except Exception as e:
   # error_log is previously opened file-like object
   error_log.write('An error occurred : %s\n' % e)

pg 87, Table 5.1

Bad indentation and missing entries.

    UnboundLocalError should be indented under NameError like this:
    NameError
      UnboundLocalError
    
  1. NotImplementedError should be indented under RuntimeError like this:
    RuntimeError
      NotImplementedError
    
  2. OverflowError is missing from the table. Should appear after FloatingPointError.
    ArithmeticError          Base for arithmetic exceptions
      FloatingPointError     Failure of a floating-point operation
      OverflowError          Integer value too large
      ZeroDivisionError      Division or modulus operation with 0
    
  3. WindowsError is missing from the table. Should appear indented under OSError.
    EnvironmentError         Errors that occur externally to Python
      IOError                I/O or file-related error
      OSError                Operating system error
        WindowsError         Windows-specific error
    

pg 90, Code example at top

Use of a better variable name in __exit__() method:

class ListTransaction(object):
    ...
    def __exit__(self,type,value,tb):
        if type is None:
            self.thelist[:] = self.workingcopy
        return False

Should be (replace "type" with "exctype"):

class ListTransaction(object):
    ...
    def __exit__(self,exctype,value,tb):
        if exctype is None:
            self.thelist[:] = self.workingcopy
        return False

pg 100, ¶5

"The fact that closures capture the environment of inner functions..."

should be

"The fact that closures capture the environment of outer functions..."

pg 101, Code example midpage

Missing underscores on __name__ attribute:

def trace(func):
    ...
           debug_log.write("%s returned %s\n" % (func.__name, r))
    ...

Should be (note extra underscores):

def trace(func):
    ...
           debug_log.write("%s returned %s\n" % (func.__name__, r))
    ...

pg 103, Code example at top

Add clarifying comment to the return:

def countdown(n):
    print("Counting down from %d" % n)
    ...
    return

Should be:

def countdown(n):
    print("Counting down from %d" % n)
    ...
    return    # Note: generators can only return None

pg 104, ¶2

"Moreover, if a program is currently iterating on generator, you should ..."

Should be:

"Moreover, if a program is currently iterating on a generator, you should ..."

pg 107, Code example at top

Fix broken code example ("find" should be "find_files"):

wwwlogs = find("www","access-log*")
...

Should be:

wwwlogs = find_files("www","access-log*")
...

pg 109, Code example midpage

Bad code comment ("f" should be "g"):

g = [math.sqrt(x*x+y*y)       # f = [2.23606, 5.0, 7.81024]
     for x,y in f]

Should be:

g = [math.sqrt(x*x+y*y)       # g = [2.23606, 5.0, 7.81024]
     for x,y in f]

pg 113, ¶3

"It is common practice for the first statement of function to be..."

Should be:

"It is common practice for the first statement of a function to be..."

pg 115, Code example at bottom

Bad code comment ("Execute" should be "Evaluate"):

...
c2 = compile(s2, '', 'eval')  # Compile into an expression
result = eval(c2)             # Execute it

Should be:

...
c2 = compile(s2, '', 'eval')  # Compile into an expression
result = eval(c2)             # Evaluate it

pg 122, Code example at top

Extra underscores in comment:

...
class Z(X,Y): pass    # TypeError.
                      # Can't create consistent method resolution order__

Should be:

...
class Z(X,Y): pass    # TypeError.
                      # Can't create consistent method resolution order

pg 123, Code example midpage

Missing module import.

class Date(object):
    ...

Should be (added line at beginning):

import time
class Date(object):
    ...

pg 124, Code example midpage

Bad attribute name (tm_month).

class Date(object):
    ...
    def now(cls):
        t = time.localtime()
        # Create an object of the appropriate type
        return cls(t.tm_year, t.tm_month, t.tm_day)

Should be ("tm_month" changed to "tm_mon")

class Date(object):
    ...
    def now(cls):
        t = time.localtime()
        # Create an object of the appropriate type
        return cls(t.tm_year, t.tm_mon, t.tm_day)

pg 125, Code example midpage

Missing parenthesis.

    def spam(self, x):
        print("%s,%s" % (self.name, x)

Should be:

    def spam(self, x):
        print("%s,%s" % (self.name, x))

pg 127, Code example at top

Bad indentation and minor correction:

class TypedProperty(object):
    def __init__(self,name,type,default=None):
        self.name = "_" + name
        self.type = type
self.default = default if default else type()
    def __get__(self,instance,cls):
        return getattr(instance,self.name,self.default)
    ...

Should be (note: there are two changed statements):

class TypedProperty(object):
    def __init__(self,name,type,default=None):
        self.name = "_" + name
        self.type = type
        self.default = type() if default is None else default
    def __get__(self,instance,cls):
        return getattr(instance,self.name,self.default) if instance else self
    ...

These changes reflect the fact that the __get__() method of a descriptor should return the descriptor itself if the instance parameter is None. This might occur if someone accesses a descriptor using the class instead of an instance.

pg 129, Code example midpage

Better comment:

u = Upperstr("hello")    # value is "HELLO"

Should be:

u = Upperstr("hello")    # u = "HELLO"

pg 132, ¶2

"For attribute lookup such as obj.name, the special method obj.__getattrribute__("name") is invoked:

Should be (fix mispelling of "getattribute)":

"For attribute lookup such as obj.name, the special method obj.__getattribute__("name") is invoked:

pg 136, code at top

def __subclasscheck__(self, sub):
    return any(c in self.implementors for c in sub.mro())

Should be

def __subclasscheck__(self, sub):
    return any(c in self.implementors for c in sub.__mro__)

pg 137, ¶5

"Although an abstract class can not be instantiated ..."

Should be ("can not" changed to "cannot"):

"Although an abstract class cannot be instantiated ..."

pg 139, ¶1

"... or supplying the metaclass keyword argument in the tuple of base classes (Python 3)."

Should be

"... or supplying the metaclass keyword argument after the tuple of base classes (Python 3)."

pg 139, code example at top

In this code example, add a small amount of space around the underscores in "__metaclass__" to make it clear that there are two leading/trailing underscores and to match the typography used elsewhere on the same page :

class Foo:                   # In Python 3, use the syntax
    __metaclass__ = type     # class Foo(metaclass=type)
    ...

pg 139, Code example near bottom

A better argument name than "dict" should be used.

class DocMeta(type):
    def __init__(self,name,bases,dict):
        for key, value in dict.items():
            # Skip special and private methods
            if key.startswith("__"): continue
            # Skip anything not callable
            if not hasattr(value,"__call__"): continue
            # Check for a doc-string
            if not getattr(value,"__doc__"):
                raise TypeError("%s must have a docstring" % key)
        type.__init__(self,name,bases,dict)

Should be (change all occurrences of "dict" to "attrs"):

class DocMeta(type):
    def __init__(self,name,bases,attrs):
        for key, value in attrs.items():
            # Skip special and private methods
            if key.startswith("__"): continue
            # Skip anything not callable
            if not hasattr(value,"__call__"): continue
            # Check for a doc-string
            if not getattr(value,"__doc__"):
                raise TypeError("%s must have a docstring" % key)
        type.__init__(self,name,bases,attrs)

pg 140, Code example in bottom half

A better argument name than "dict" should be used.

class TypedMeta(type):
    def __new__(cls,name,bases,dict):
        slots = []
        for key,value in dict.items():
            if isinstance(value,TypedProperty):
                value.name = "_" + key
                slots.append(value.name)
        dict['__slots__'] = slots
        return type.__new__(cls,name,bases,dict)

Should be (change all occurrences of "dict" to "attrs"):

class TypedMeta(type):
    def __new__(cls,name,bases,attrs):
        slots = []
        for key,value in attrs.items():
            if isinstance(value,TypedProperty):
                value.name = "_" + key
                slots.append(value.name)
        dict['__slots__'] = slots
        return type.__new__(cls,name,bases,attrs)

pg 147, ¶6

"First, it is only possible import .py, .pyw, .pyc, and .pyo files from an archive."

Should be:

"First, the only file types that can be imported from an archive are .py, .pyc, .pyo, and .pyw."

pg 150, ¶6 (near bottom)

"To do this, you can simply use the fully specified named (e.g., ..."

Should be ("named" changed to "name"):

"To do this, you can simply use the fully specified name (e.g., ..."

pg 152, Code example in middle

Use more consistent indentation:

# setup.py
from distutils.core import setup

setup(name = "spam",
            version = "1.0",
            py_modules = ['libspam'],
            packages = ['spampkg'],
            scripts = ['runspam.py'],
            )

Should be:

# setup.py
from distutils.core import setup

setup(name = "spam",
      version = "1.0",
      py_modules = ['libspam'],
      packages = ['spampkg'],
      scripts = ['runspam.py'],
      )

pg 160, Table 9.1

Change the description for f.fileno().

"Returns an integer file descriptor."

Should be:

"Returns the integer file descriptor or raises ValueError if closed."

pg 163, ¶4 (midpage)

Add a clarifying note:

"To suppress or change the line ending, use the end=ending keyword argument. For example:"

Should be:

"To suppress or change the line ending, use the end=ending keyword argument (note: if you specify something other than a newline, you may have to flush sys.stdout to see the output)."

pg 164, code example at top

Messy formatting.

print form % { 'name' : 'Mr. Bush',
               'item' : 'blender',
               'amount' : 50.00
                 }

Should be (just move the brace)

print form % { 'name' : 'Mr. Bush',
               'item' : 'blender',
               'amount' : 50.00 }

pg 165, code example midpage

Missing parenthesis.

...
        buffered_size = 0
out.write("".join(chunks)

Should be (note extra ')' at end):

...
        buffered_size = 0
out.write("".join(chunks))

pg 173, Table 10.1

The font on "-Q arg" is wrong. The '-Q' should be monospaced like other options and "arg" should be monospaced italics. See the "-m module" entry for an example.

pg 191, ¶4

"If you simply want to time a long-running Python program, the easiest way to do it is often to just run it until the control of something..."

Should be ("until" replaced by "under")

"If you simply want to time a long-running Python program, the easiest way to do it is often to just run it under the control of something..."

pg 194, midpage

Bad font for section headers. The "Understand Algorithms" and "Use the Built-In Types" headers should be typeset in the same font as used for the "Understand Your Program" header above.

pg 203, midpage

Add Python 3 note to cmp() description.

"... In certain circumstances, such comparisons may also raise an exception."

Should be

"... In certain circumstances, such comparisons may also raise an exception. Python 3 only."

pg 204, midpage

Missing ] and extra space.

"enumerate(iter [, initial value)"

Should be (note extra ']' at end and added underscore in "initial_value")

"enumerate(iter [, initial_value])"

pg 206, midpage

Add clarifying note to input() description.

"... line of input is read without any kind of evaluation or modification."

Should be

"... line of input is read without any kind of evaluation or modification. The returned line does not include a trailing newline character."

pg 210, top

Typo in description of slice()

"Slice objects are also generated by the extended slice syntax a[i:i:k]."

Should be (change second "i" to "j")

"Slice objects are also generated by the extended slice syntax a[i:j:k]."

pg 213, bottom

In description of FloatingPointError:

"It should be noted that floating-point exception handling is a tricky problem and only that this exception only gets raised if..."

Should be (delete "only"):

"It should be noted that floating-point exception handling is a tricky problem and that this exception only gets raised if..."

pg 226, midpage

Clarify the use of byte strings (marshal module). Changes in multiple places.

  1. Description of dumps():

    "Returns the string written by..."

    Should be (add "byte")

    "Returns the byte string written by..."

  2. Heading for loads():

    "loads(string)" should be "loads(bytes)".

  3. Description of loads():

    "Reads and returns the next value from the string string."

    Should be:

    "Reads and returns the next value from the byte string bytes."

pg 227, midpage

Clarify the use of byte strings (pickle module). Changes in multiple places.

  1. Description of dumps():

    "Same as dump(), but returns a string containing the pickled data."

    Should be (add "byte")

    "Same as dump(), but returns a byte string containing the pickled data."

  2. Heading for loads():

    "loads(string)" should be "loads(bytes)".

  3. Description of loads():

    "Same as load(), but reads the pickled representation of an object from a string.

    Should be (add "byte"):

    "Same as load(), but reads the pickled representation of an object from a byte string.

pg 233, midpage

Typo and confusing typography in description of displayhook().

"... is printed to standard output and value is saved in the variable __builtin__._.displayhook can be redefined..."

Should be (extra 's' on '__builtins__' and added text):

"... is printed to standard output and value is saved in the variable __builtins__._. The displayhook function can be redefined..."

pg 237, note at bottom

"The types module should not be used to refer the type of ..."

Should be (added "to"):

"The types module should not be used to refer to the type of ..."

pg 242, code example at top

Use modern idioms in code:

def foocache(x):
     if resultcache.has_key(x):
        ...

Should be

def foocache(x):
     if x in resultcache:
        ...

pg 259, Table 15.1

Delete the entire first entry in the table. This is the entry that looks like:

'c'      8-bit character        char           1

Note: This isn't supported in Python 3 and using it in Python 2 is probably ill-advised anyways.

pg 260, code at bottom

Typo in code comment:

b = array.array(a.typecode, (2*x for x in a))  # Create a new array from b

Should be (change "b" to "a")

b = array.array(a.typecode, (2*x for x in a))  # Create a new array from a

pg 283, midpage

Use a better argument name in compile()

"compile(str [, flags])"

Should be (change "str" to "pattern")

"compile(pattern [, flags])"

pg 288, last line

Bad quotation mark on '0.name'. The ending quotation mark should be straight.

pg 300, code at bottom

Bad indentation.

  symbol = "AIG"
account = 12345

Should be

symbol = "AIG"
account = 12345

pg 300, 2nd to last paragraph

Add a clarifying sentence:

"Here the '?' placeholders are successively replaced with values from the tuple (symbol, account)."

Should be

"Here the '?' placeholders are successively replaced with values from the tuple (symbol, account). '?' can only be used for values, not other parts of the query such as the command or table name."

Layout note: To add the above sentence, you might have to make space (suggest using extra space right above the "Forming Queries" heading).

pg 311, ¶3

In description of open()

"... has the same meaning as described in the chapter introduction and is ..."

Should be

"... has the same meaning as described in the previous section and is ..."

pg 311, midpage

In table describing operations on shelves:

d.has_key(key)

Should be

key in d

pg 313, bottom

In description of c.compress():

"Feeds new string data to the compressor object, c. Returns a string of compressed data if possible. Because compression involves chunks of data, the returned string may not include..."

Should be (add "byte")

"Feeds new byte string data to the compressor object, c. Returns a byte string of compressed data if possible. Because compression involves chunks of data, the returned byte string may not include..."

pg 314, top

In description of c.flush():

"Flushes the internal buffers and returns a string containing..."

Should be (add "byte")

"Flushes the internal buffers and returns a byte string containing..."

pg 314, top

In description of d.decompress():

"Given a chunk of compressed data in the string data, this method returns uncompressed data. Because data is processed in chunks, the returned string may or may not ..."

Should be (add "byte")

"Given a chunk of compressed data in the byte string data, this method returns uncompressed data. Because data is processed in chunks, the returned byte string may or may not ..."

pg 314, midpage

In description of compress():

"Returns a compressed version of the data supplied in the string data."

Should be (add "byte")

"Returns a compressed version of the data supplied in the byte string data."

pg 314, midpage

In description of decompress():

"Returns a string containing the decompressed data in the string data."

Should be (add "byte")

"Returns a byte string containing the decompressed data in the byte string data."

pg 316, last line of code

Last line of code is missing parentheses:

for pyfile in findall(".","*.py"):
    print pyfile

Should be (add parens):

for pyfile in findall(".","*.py"):
    print(pyfile)

pg 333, near bottom

In the description of c.items().

There is a bad quotation mark style used in the sentence with "values that can be used in '%' expansions." Use straight quotes.

pg 349, code at top of page

Use modern exception handling style:

...
except IOError,e:
    print "Unabled to acquire lock", e

Should be:

...
except IOError as e:
    print("Unabled to acquire lock %s" % e)

pg 356, code midpage

Missing comma in arguments:

logging.basicConfig(
   filename = "app.log",
   format   = "%(levelname)-10s %(asctime)s %(message)s"
   level    = logging.INFO
)

Should be (note extra comma on third line):

logging.basicConfig(
   filename = "app.log",
   format   = "%(levelname)-10s %(asctime)s %(message)s",
   level    = logging.INFO
)

pg 398, midpage

Extra space in in description for split():

"For example, '/home/user/foo' gets split into ('/home/ user', 'foo')."

Should be (eliminate extra space in '/home/ user')

"For example, '/home/user/foo' gets split into ('/home/user', 'foo')."

pg 403, ¶3 midpage

Add an extra blank line before this sentence to better separate it from the description of check_call() above it.

"The Popen object p returned by Popen() has a variety of..."

Layout note: To do this, there is some extra blank space at the end of the table at the top of the page. Perhaps the description of call() can be moved up to make room.

pg 406, bottom half

In description of sleep():

"Puts the current process to sleep for ..."

Should be (change "current process" to "calling thread"):

"Puts the calling thread to sleep for ..."

pg 408, bottom half

In description of ConnectRegistry():

"key is a predefined handle such as HKEY_CURRENT_USER or HKEY_ USERS."

Should be (removed extra space in HKEY_USERS):

"key is a predefined handle such as HKEY_CURRENT_USER or HKEY_USERS."

pg 414, ¶3

"There's a joke attributed to Jason Whittington that goes as like this:"

Should be (remove "as"):

"There's a joke attributed to Jason Whittington that goes like this:"

pg 415, ¶2

In the 2nd to last sentence of this paragraph.

"... For example, a coroutine is a function that can receive and processe messages that are sent to it."

Should be (fix spelling of "process"):

"... For example, a coroutine is a function that can receive and process messages that are sent to it."

pg 416, top

In description of Process():

"... The arguments in the constructor should always been specified using ..."

Should be (change "been" to "be")

"... The arguments in the constructor should always be specified using ..."

pg 416, middle

In description of p.join():

"it is an error for a process to try and join itself."

Should be

"it is an error for a process to try to join itself."

pg 417, bottom

"... to run the preceding examples in the command shell (command.exe) instead of a ..."

Should be (change "command" to "cmd"):

"... to run the preceding examples in the command shell (cmd.exe) instead of a ..."

pg 426, ¶3 midpage

"Normally, processes are completed isolated from each other..."

Should be (change "completed" to "completely"):

"Normally, processes are completely isolated from each other..."

pg 465, code example, midpage

Change the implementation of the send() method so that it doesn't use the built-in "bytes" name.

...
def send(self,bytes):
    while bytes:
        evt = yield WriteWait(self.sock)
        nsent = self.sock.send(bytes)
        bytes = bytes[nsent:]
...

Should be (change "bytes" to "data"):

...
def send(self,data):
    while data:
        evt = yield WriteWait(self.sock)
        nsent = self.sock.send(data)
        data = data[nsent:]
...

pg 493, bottom

In description of Server.verify_request():

"Redefine this method if you want to verify the connection before any further processing. This is what you define if you want to implement a firewall or perform some other kind of a validation."

Should be (reworded for consistency):

"Method that is called to verify the connection before any further processing. By redefining this method, you can implement a firewall or perform other kinds of validation."

pg 493, bottom

In second to last paragraph.

"Finally, addition server features are available..."

Should be:

"Finally, additional server features are available..."

pg 497, bottom

In description of f.abort():

"Attempts to abort a file transfer that is in progress. This may or may not work depending the remote server."

Should be (add missing "on"):

"Attempts to abort a file transfer that is in progress. This may or may not work depending on the remote server."

pg 518, bottom

In description of install_opener():

"Installs a different opener object for use as the global URL opener used by urlopen(). opener is usually of an opener object created by build_opener().

Should be (delete "of"):

"Installs a different opener object for use as the global URL opener used by urlopen(). opener is usually an opener object created by build_opener().

pg 532, last sentence

"The topics of web frameworks is far beyond the scope..."

Should be (change "topics" to "topic"):

"The topic of web frameworks is far beyond the scope..."

pg 536, bottom

In description of parse_header():

('text/html', {'a':'hello', 'b':'world'})
parse_multipart(fp, pdict)

Should be (delete the second line):

('text/html', {'a':'hello', 'b':'world'})

pg 538, code at top

# Print the output page
values = {
   'name' : name,
   'email' : email,
   'confirmation: ': confirmation,
   # Add other values here...
}

Should be (delete the extra ' :' after the word 'confirmation' on the third line):

# Print the output page
values = {
   'name' : name,
   'email' : email,
   'confirmation' : confirmation,
   # Add other values here...
}

pg 570, ¶3

In description of parse():

"ile is a filename or already-open file object."

Should be:

"file is a filename or already-open file object."

pg 588, last table

The table entry for sched should be deleted. This module was already listed on page 587.

pg 624, bottom third of page

>>> foo.__annotations__
{'y': 4, 'x': 3, 'return': 5}
>>>

Should be (values are corrected):

>>> foo.__annotations__
{'y': 2, 'x': 1, 'return': 3}
>>>

pg 628, code at bottom

class MultiMeta(type):
    ...
    def __new__(cls, name, bases, classdict):
        for name in classdict.multiple:
            print(name, 'multiply defined')
        if classdict.multiple:
            raise TypeError('Multiple definitions exist')
        return type.__new__(cls, name, bases, classdict)

Should be changed to avoid variable name clash

class MultiMeta(type):
    ...
    def __new__(cls, clsname, bases, classdict):
        for name in classdict.multiple:
            print(name, 'multiply defined')
        if classdict.multiple:
            raise TypeError('Multiple definitions exist')
        return type.__new__(cls, clsname, bases, classdict)

pg 638, last paragraph

"For Python 3, especially, it is critically to report bugs, ..."

Should be (added "important"):

"For Python 3, especially, it is critically important to report bugs, ..."

pg 686, top of first column

Index entry for "numeric type coercision" should be "numeric type coercion"

pg 695, bottom part of first column

Index entry for "readlines() method of StreamReder objects" should be "readlines() method of StreamReader objects"

pg 712, middle of first column

Index entry for "Unicode strings, encoding and decoing" should be "Unicode strings, encoding and decoding"


Copyright (C) 2005-2024, David Beazley