Errata

Head First Python

Errata for Head First Python

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
Page Chapter 7 Task4
in code: "req.user_agent.browser"

2nd Edition from Amazon, Running on the newest version in a ubuntu LTS, virtual environment as of 5/29/23:

req.user_agent or req.user_agent.browser crashed when "Do it" was pressed. If substitute 'test', the data is written to the mysql database.

req.remote_addr seems okay, so don't know why req.user_agent does not work. Why?

Note from the Author or Editor:
Due to an update in the underlying library, req.headers.get('User-Agent') should now be used.

Brett  May 30, 2023 
Page xxxv & 216
URL

http : / / python.itcarlow.ie & http : / / python.itcarlow.ie/ed2 are not accessible. Trying to get access to html/css templates for webapp project.

Note from the Author or Editor:
Isn't progress a wonderful thing...? Nowadays, it's "https".

Ryan Weckesser  May 17, 2022 
Page chapter 10
text

Typo

Current Copy
learned on the last page, we need two things: A way to store variables without resorting to using globals A way to keep one webapp user’s data from interferring with another’s Most webapp development frameworks (including Flask) provide for both of these requirements using a single technology: the session.

Suggested
"user’s data from interferring with another’s" should be "user’s data from interfering with another’s"

Note from the Author or Editor:
Typo on page 367 (second bullet point) confirmed.

Anonymous  Mar 17, 2022 
Page 287
3rd paragraph

When I changed to MariaDB as you previously recommended, I couldn't get the database to work. I used the command line prompt of MariaDB [None]> as printed on the page but my computer responded that the syntax wasn't correct. What am I doing wrong?

Note from the Author or Editor:
It's not clear which command is causing an issue. However, if it is this command:

grant all on vsearchlogDB.* to 'vsearch' identified by 'vsearchpasswd';

please adjust (with recent versions of MariaDB) to this:

grant all on vsearchlogDB.* to 'vsearch'@'localhost' identified by 'vsearchpasswd';

Anonymous  Jan 13, 2022 
Page 347
code at the top of page

When I run the code with MySQL 8.0 I get the following error:
>>> from DBcm import UseDatabase

Traceback (most recent call last):

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

from DBcm import UseDatabase

File "C:\Users/kenni/OneDrive/Documents/Head_First_Python/webapp\DBcm.py", line 1, in <module>

import mysql.connector

ModuleNotFoundError: No module named 'mysql'

I have MySQL 8.0 running and have the exact code as written on that page in my class. When I try to run it I get this traceback error.

Another problem is that you need to update how to install MySQL 8.0. It requires a password and you cannot get by just by pressing the Enter button twice. Furthermore, you need to install an OCBC driver in addition to MySQL 8.0. All of these issues need to be addressed. Otherwise I have enjoyed your book, apart from these technical issues.

Note from the Author or Editor:
I've found that removing MySQL from your computer and installing MariaDB instead fixes this issue.

--Paul.

Anonymous  Jan 06, 2022 
Page 162
search4vowels function definition

I am challenging the idea of introducing annotation syntax but immediately ignoring PEP 8 style guidelines, first introduced on page 153, (even though that is indeed covered later). This is unnecessarily confusing for someone who read PEP 8 before getting to page 162.

Using ":str" here instead of ": str" creates a less desirable habit right away, and it isn't addressed until page 192.

Likewise, on page 170, PEP 8 specifies to add space around the assignment operator for an annotated default value, where "letters:str='aeiou'" ought to be "letters: str = 'aeiou'".

Maybe there is a different way to approach the value of using PEP 8 compliance tools without having the learner start off on the wrong foot?

Note from the Author or Editor:
This is something (i.e., annotations) that were relatively new when the second edition was being written and - in hindsight - was not handled at all well in the book. The 3rd edition is being actively worked on now (Sept 2021) and I'm toying with the idea of removing annotations altogether.

Anonymous  Aug 21, 2021 
Page 182
"Step 3 on UNIX-like OSes": its first paragraph, and also the command to use

The folder in the UNIX-like OSes should be 'dist' just like for Windows. This is incorrect in two places. [Was also reported January 2017, marked corrected in July 2017, but apparently didn't make it to the 2e print.]

Summary:
Change 'dict' to 'dist'
"within the newly created dist folder"
".../dist$ sudo python3 -m pip install vsearch-1.0.tar.gz"

Note from the Author or Editor:
Change all uses of "dict" to "dist" on this page.

Anonymous  Aug 21, 2021 
Page n/a
Location in ePub: 2108

There is a URL that no longer works reported from Amazon:

flask.pocoo[dot]org/docs/0.11/api/#sessions", at location 113 "headfirstlabs[dot]com/books.php". Please update a valid external URL. To ensure future access to reference material, Amazon strongly recommends submitting these types of links to an archive service, and including the archived link in the book. If the link is broken due to forces outside your control, it should be deactivated and "[URL inactive]" should be added following the link text."

Note from the Author or Editor:
The Flask pocoo URL should be changed to read: https://flask.palletsprojects.com/en/2.0.x/api/?highlight=session#flask.session while the Head First Labs URL should be changed to read: https://learning.oreilly.com/search/?query=Head%20First.

Anonymous  Aug 02, 2021 
Page Ch 2... Section: An Unordered Data Structure: Dictionary
Section of chapter two named: "An Unordered Data Structure: Dictionary"

The name of the chapter 2 section "An Unordered Data Structure: Dictionary" correctly reflected Python at the time the 2nd edition was published, but I believe that Python dictionaries have been ordered by default (not unordered) for some time now. Are "language change" updates being made in, say, the PDF version or the Safari Book Online? If yes, there are several places in the book where a dictionary is considered an unordered data structure... to be honest, after a ton of research and finding that when I was satisfied with the errata... I was happily reading the book until I came to this. So I'd be super interested to hear what the position is on an issue like this.

Warm regards... and this is absolutely a great book!!

Jason

Note from the Author or Editor:
The second edition targets Python 3.5 which behaves as described in the book. And, of course, things have changed since publication. The newer ordering behaviour is on the list of "things to fix" for the third edition which is currently under development. The plan is for the new edition of Head First Python to target release 3.10 of Python. There are no plans to retrofit the second edition of the book with these types of fixes.

Anonymous  Jun 25, 2021 
Printed, PDF, ePub, Mobi, , Other Digital Version
Page 285
4th paragraph

The link to the MySQL-Connector/Python driver page works fine, but when you arrive at the site there is no longer a 'Platform Independent' option from the dropdown menu when you want to download. You must either select an OS or go with the Source Code option.

Note from the Author or Editor:
This is correct. Oracle changed how this works (per this reader's note). Scheduled to be fixed in the 3rd edition, but a quick fix for now is to simply run "pip install mysql-connector-python" as Oracle have improved support here too.

Billy Hawes  Feb 21, 2021 
Printed, PDF, ePub, Mobi, , Other Digital Version
Page 230
Page 230, 1st paragraph, results.html template

In the 9th line of the results.html template, "is search for" should be "is searched for".

Note from the Author or Editor:
Confirmed: "is search for" should be "is searched for". As a result of this typo, the outputs generated on page 233 also contain the error. Also pages 252 and 253 - same issue with the output.

Bill Scharf  Jan 22, 2021 
, Printed, PDF, ePub, Mobi, , Other Digital Version
Page 191
Center of page screen shot

When I run py.test --pep8 vsearch.py from a shell command my results are quite different. It doesn't seem to be running the test, and I can't figure out why.

PS C:\-pathsnipped-> py.test --pep8 vsearch.py
c:\python38\lib\site-packages\pep8.py:110: FutureWarning: Possible nested set at position 1
EXTRANEOUS_WHITESPACE_REGEX = re.compile(r'[[({] | []}),;:]')
========================= test session starts =====
platform win32 -- Python 3.8.5, pytest-6.0.1, py-1.9.0, pluggy-0.13.1
rootdir: C:\-pathsnipped-
plugins: pep8-1.0.6
collected 0 items / 1 error

================================ ERRORS ==========
______________ ERROR collecting test session ______________
c:\python38\lib\site-packages\pluggy\hooks.py:286: in __call__
return self._hookexec(self, self.get_hookimpls(), kwargs)
c:\python38\lib\site-packages\pluggy\manager.py:93: in _hookexec
return self._inner_hookexec(hook, methods, kwargs)
c:\python38\lib\site-packages\pluggy\manager.py:84: in <lambda>
self._inner_hookexec = lambda hook, methods, kwargs: hook.multicall(
c:\python38\lib\site-packages\pytest_pep8.py:38: in pytest_collect_file
return Pep8Item(path, parent, pep8ignore, config._max_line_length)
c:\python38\lib\site-packages\_pytest\nodes.py:95: in __call__
warnings.warn(NODE_USE_FROM_PARENT.format(name=self.__name__), stacklevel=2)
E pytest.PytestDeprecationWarning: Direct construction of Pep8Item has been deprecated, please use Pep8Item.from_parent.
E See https://docs.pytest.org/en/stable/deprecations.html#node-construction-changed-to-node-from-parent for more details.
======================= short test summary info =============
ERROR - pytest.PytestDeprecationWarning: Direct construction of Pep8Item has been deprecated, please use Pep8Item.from_parent.
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Interrupted: 1 error during collection !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
=========================== 1 error in 0.26s ============



Note from the Author or Editor:
Here's some notes from another reader on this issue:

"...However, after going through the internet looking for answers I found a solution that produced the same output as the one in your book! A forum user posted that the pep8 part of pytest is being renamed to pycodestyle, so when I type

sudo -H python3 -m install pytest-pycodestyle

it installs the module to check for pep8 compliance, and then call it by

pytest —pycodestyle *.py

I’m not sure if it is a separate module all together, or it actually is the new name for the pep8 module, but pycodestyle seems to give the same terminal output as pep8 would... "

Note that the published book targets Python 3.5 and that time marches on. 3.9 is just around the corner and pytest 6 recently appeared. Some things change and stuff in the book breaks. This is hard to avoid.

--Paul.

Polly  Aug 25, 2020 
, Printed, PDF, ePub, Mobi, , Other Digital Version
Page 564
First paragraph

"(which he started as a 'hobby' in the last 1980s)"
should be "in the late 1980s".

Note from the Author or Editor:
Please change "last 1980s" to "late 1980s" (end of first sentence).

Anonymous  May 31, 2020  Jun 19, 2020
, Printed, PDF, ePub, Mobi, , Other Digital Version
Page 505
First paragraph

"A set comprehensions" in the beginning of the first sentence.
Should be "A set comprehension".

Note from the Author or Editor:
Drop the "s" from the end of the word "comprehensions" - first sentence.

Anonymous  May 31, 2020  Jun 19, 2020
Printed, PDF, ePub, Mobi,
Page 71
Second bullet point

'List are similar...' should be 'Lists are similar...'

Note from the Author or Editor:
Change "List" to "Lists" at start of second bullet point.

Bastian Holtermann  Jan 14, 2020  Jan 31, 2020
Printed, PDF, ePub, Mobi,
Page 313
Bottom Code

I have done the step by step procedure until this point but these next few lines are ringing error on my IDLE window:
=======Head First Python (Code) ============
>>> c = CountFromBy()
>>> c
0
>>> c.increase()
>>> c.increase()
>>> c.increase()
>>> c
3
=======================================


My IDLE window error:

>>> class CountFromBy:
pass

>>> c = CountFromBy()
>>> c
<__main__.CountFromBy object at 0x02DFE990>

======================================
I have even added the increase function as described in errata page but the same issue prevails:

>>> class CountFromBy:
def increase(self) ->None:
self.val += self.incr


>>> class CountFromBy:
pass

>>> c = CountFromBy()
>>> c
<__main__.CountFromBy object at 0x02DFE990>
>>> c.increase()
Traceback (most recent call last):
File "<pyshell#23>", line 1, in <module>
c.increase()
File "<pyshell#20>", line 3, in increase
self.val += self.incr
AttributeError: 'CountFromBy' object has no attribute 'val'


==============================================

Requesting assistance on the same.

Regards
ABHAY

Note from the Author or Editor:
The more I look at this material, the more I realise that I did a pretty poor job of presenting this topic. On page 325 (bottom half) you'll find the code required to make this all work - my mistake was to show the code running before I'd presented the code in it's totality.

Abhay  Jan 12, 2020  Jan 31, 2020
PDF, ePub, Mobi, , Other Digital Version
Page 54
Code comments

The period is missing at the end of "A list of the odd numbers".

Note from the Author or Editor:
Add period to end of first annotation.

Bastian Holtermann  Nov 05, 2019  Jan 31, 2020
Printed, PDF, ePub, Mobi, , Other Digital Version
Page 45
Bullet points

At the end of the 4th bullet point the period is missing.

Note from the Author or Editor:
And, indeed it is.

Bastian Holtermann  Nov 03, 2019  Jan 31, 2020
PDF
Page 312
2

I have followed steps given in PDF, however, getting some issues as follows. Am I making any mistake here

---------------------------------------------------------------------------------------------------------------------------

Python 3.8.0 (default, Oct 14 2019, 21:29:03)
[GCC 7.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> class CountFromBy:
... pass
...
>>> a = CountFromBy()
>>> b = CountFromBy()
>>> c = CountFromBy()
>>> c
<__main__.CountFromBy object at 0x7f9b3a082a90>
>>> a
<__main__.CountFromBy object at 0x7f9b3a052460>
>>> b
<__main__.CountFromBy object at 0x7f9b3a037520>
>>> c.increase()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'CountFromBy' object has no attribute 'increase'
>>> c
<__main__.CountFromBy object at 0x7f9b3a082a90>
>>>


---------------------------------------------------------------------------------------------------------------------------

Note from the Author or Editor:
The error I made was to show (on pages 312ff) the increase() method in use before the code for it is defined. See the top of page 320 for what you have to add.

Ramesh  Nov 03, 2019  Jan 31, 2020
Printed, PDF, ePub
Page 44
5th paragraph

In the explanation of the for loop there is "... from 99 down to none." but I would explain it with counting "... from 99 down to 1." since the value 0 is not included in the loop.

Note from the Author or Editor:
Yes, the description could be clearly here. Better to use the words "down to but not including zero" instead of "none".

Bastian Holtermann  Oct 23, 2019  Jan 31, 2020
Printed, PDF, ePub
Page 35
1st paragraph

I found it confusing that the renaming from odd.py to odd2.py is made on page 35 after finishing the last two tasks instead of renaming the file after the first task (the for loop) is inserted to the file.

Would be more consequent to have an odd.py file without loop etc. and an odd2.py file with the changes of all three tasks.

Note from the Author or Editor:
Noted. Addressing this has been added to the list of tasks for the 3rd edition.

Bastian Holtermann  Oct 22, 2019 
Printed, PDF, ePub
Page 36
1st paragraph

"things we're learned" should be "things we've learned"

Note from the Author or Editor:
Well spotted.

Bastian Holtermann  Oct 22, 2019  Jan 31, 2020
Printed, PDF, ePub, Mobi,
Page 237
Second to last bullet point

The book says "A function can be decorated more than once (as you saw with the do_search function)."

The function that was decorated twice was named "entry_page()"

Note from the Author or Editor:
Yes, first bullet point on RHS of bullet list has a minor error at the end of the paragraph (inside the parens). So... "with the do_search function" should read "with the entry_page function".

David Escobar  Jun 11, 2019  Jul 12, 2019
Printed, PDF, ePub, Mobi,
Page 533
Both parts of Step 3

Step 3 (extract and install your code) appears to be inaccurate, or is perhaps out of date.

The first line of code (python3 -m pip install vsearch.zip --user) throws up an error:

21:43 ~ $ python3 -m pip install vsearch.zip --user
Looking in links: /usr/share/pip-wheels
Processing ./vsearch.zip
Complete output from command python setup.py egg_info:
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/usr/lib/python3.7/tokenize.py", line 447, in open
buffer = _builtin_open(filename, 'rb')
FileNotFoundError: [Errno 2] No such file or directory: '/tmp/pip-req-build-qyaox0bn/setup.py'

----------------------------------------
Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-req-build-qyaox0bn/

SOLUTION: I got around this by unzipping the file first, then installing vsearch by typing: python3 -m pip install vsearch --user

It seems the two parts to this step are the wrong way around.

Note from the Author or Editor:
The PythonAnywhere instructions are to be reviewed and updated in a later edition (as they do change from time to time).

Alan Wilson  Apr 24, 2019 
Printed
Page 287
last paragraph

The Line

grant all on vsearchlogDB.* to 'vsearch' identified by 'vsearchpasswd';

does not work with MySQL 8.0 running Windows 7/10. User has to be created and granted separately:

create user 'vsearch' identified by 'vsearchpasswd';
grant all on vsearchlogDB.* to 'vsearch';

Note from the Author or Editor:
This isn't really errata as v8 of MySQL was released 2 years after this book published. However, I'm going to include it here so that other readers aren't tripped up by this (and I've noted this change for future updates).

Anonymous  Sep 03, 2018 
Printed
Page 313
bottom

The beginning of chapter 8 did a good job preparing the reader for how Python deals with OOP, but suddenly, out of nowhere, appears the "increase" method for the CountFromBy class. I've had some experience with OOP and was confused where this method came from!? The reader should have been warned that the def for this class would be forthcoming and not left scratching their head wondering how it got there. Better yet, give the def for the increase function within the CountFromBy class and then proceed with the dot notation, etc... Don't just pull it out of the air!

Note from the Author or Editor:
Noted for reworking during next update. The text needs to be clearer in its intention to work up to creating the "increase" method.

bromberg  Sep 02, 2018 
Printed
Page 258
code (in bold) near top

In the code above TEST DRIVE on page 258 you write:
contents=log.read()
but in the code at the bottom of page 268 you write:
contents=log.readlines()

Is there a difference between the read and readlines functions?

Note from the Author or Editor:
The distinction needs to be clearer here: "read" grabs the entire file into a string (series of bytes), whereas "readlines" grabs the entire file into a list of lines (i.e., a list of strings).

dan bromberg  Aug 31, 2018 
Printed
Page copyright

Add credit to copyright page:
Brain image on spine: Eric Freeman

O'Reilly Media
 
Apr 10, 2018  Jun 01, 2018
ePub
Page 405
First paragraph

"The first file, which must be called setup. py, describes our module in some detail."

Note there is a spurious space between setup. and py

Should be setup.py

Note from the Author or Editor:
Not an issue in PDF or printed book, but please check the ePub version (note: this is on page 179 of PDF, second paragraph).

Robert Robb Livingston  Dec 17, 2017  Jan 05, 2018
PDF
Page 453
Last sentence

"you can add an elif suite to the end of the __exit__ method that reraises the unexpected exception"

You need to say something about why it is useful to reraise the unexpected exception. After all, it was unexpected before, why won't it be unexpected again?

Note from the Author or Editor:
I did start this paragraph off with the statement "If you want to be extra safe..." which was meant to hint that this was taking things to a bit of an extreme. I've made a note to extend this description in the next edition.

Jon Forrest  Aug 10, 2017 
PDF
Page 453
In __exit__ method

"if exc_type is mysql.connector.errors.ProgrammingError:"

You need to say something about why you used "is" rather than "==".

Note from the Author or Editor:
Noted for (potential) third edition.

Jon Forrest  Aug 10, 2017 
PDF
Page 430
2nd to last paragraph

"it does this without you having to remember to import the sys module"

But you do have to remember to import the sys module for the sample above to work. The sample even clearly says "Be sure to import the "sys" module"

Note from the Author or Editor:
Second last paragraph, at the end of the sentence, it reads: "...and it does this without you having to remember to import the sys module, or wrangle with the tuple returned by that function."

Change this to read: "...and it does this without you having to remember to import nor interact with the sys module, nor wrangle with the tuple returned by the exc_info function."

Note 1: "exc_info" above should be in code-font.

Note 2: This paragraph refers to the generic way try/except works which is explored over the page. I should've made this fact clearer.

Jon Forrest  Aug 09, 2017  Jan 05, 2018
PDF
Page 424
2nd to last line

(Another trivial issue)

"The except statement and its suite is new code." ->
"The except statement and its suite are new code."

Note from the Author or Editor:
Second last sentence at bottom of page. Change "The except statement and its suite is new code." to read: "The except statement (and its associated suite) is new code."

Jon Forrest  Aug 09, 2017  Jan 05, 2018
PDF
Page 427
right-hand caption

(Another trivial error you've made before)

"Here's the two exceptions ..." ->
"Here are the two exceptions ..."

Note from the Author or Editor:
Annotation on RHS of page: "Here's the two" should read "Here are the two".

Jon Forrest  Aug 08, 2017  Jan 05, 2018
PDF
Page 425
2nd figure caption

(a very trivial issue)

"... produces a much friendlier messages ..." ->
"... produces a much friendlier message ..."

Note from the Author or Editor:
Change "messages" to "message" in the annotation directly below the first image.

Jon Forrest  Aug 08, 2017  Jan 05, 2018
PDF
Page 404
whole page

Your description of decorators needs more meat. For example,

1) You've used the word decorator in 2 ways, e.g as the thing on the line
starting with a '@' character, and as the function that must meet the
requirements stated on page 395. Is this correct?

2) What's the syntax for invoking a decorator? We've seen 3 examples

@app.route('/page1')
@wraps(func)
@check_logged_in

The first 2 use a similar syntax, but only the 2nd explicitly passes the name of the function being decorated. The 3rd says nothing. When does a decorator require arguments?

3) What does

@check_logged_in

actually do at runtime?

4) Apparently the decorated function is magically passed as an argument to the decorator. How does this work?

Note from the Author or Editor:
There's a lot more to decorators than space allowed me to cover in the 2nd edition. What's shown in Chapter 10 is by way of introduction, as doing a deep-dive with decorators would be considered one of the more advanced Python topics. What's shown is designed to prime a reader to tackle more detailed coverages in other texts (for instance: the Python Cookbook, 3rd edition, has some very good material). Your comments/questions are noted for inclusion/consideration in an updated edition. Thanks.

Jon Forrest  Aug 05, 2017 
PDF
Page 395
Whole page

You list 4 features that a decorator must have. But, the decorators that we've used already, such as one first defined on page 207, only include the first of these features. How can the decorators we've used be decorators with these features missing?

Note from the Author or Editor:
Note for editor: There is *no* change required to the text.

However, a clarification is needed here: In order to use an existing decorator, all you need to know is what it does, and how to use it (as per the example on page 207). To create your own decorator (which can later be used by you and/or by others) you need to know about and understand the four things listed on page 395. When it comes to creating a decorator, these four things are prerequisites from a knowledge point-of-view, not absolute requirements from an implementation point-of-view. That is, knowing about them helps you get your head around what's possible with decorators. What your decorator ends up doing is an implementation-dependent detail as the decorator machinery is a generic mechanism which can be put to many uses.

Jon Forrest  Aug 03, 2017 
PDF
Page 371
1st paragraph

"When we opened up Safari (or you can use Edge if you are on Windows), we used the webapp’s other URL, /getuser, to retrieve the current value of user from the webapp."

You write as if you had shown an example of using the /getuser URL. But, I don't see such an example on the preceding pages. Is something missing?

Note from the Author or Editor:
Change the first paragraph on this page to read:

If you open up Safari (or Edge if you are on Windows), and use the webapp’s other URL, /getuser, you'd expect to retrieve the current value of user from the webapp. However, when you do this in Safari (or Edge), you’re greeted with a rather intimidating error message:

Jon Forrest  Jul 30, 2017  Jan 05, 2018
PDF
Page 271
In example code

Up until now, you've always said "-> str". Now, all of a sudden, you say "-> 'str'" (note the quotes). In fact, on this page you have both.

You first quoted a return type on Pg. 218 with 'html'.

I know that Python doesn't care what the denotations are but you should be consistent.

Note from the Author or Editor:
Change usage of:
-> 'str'
to read:
-> str
on pages 271, 272, 273, and 276.

Also, on pages 271 and 272, the @app.route('/viewlog') line of the shown code (the first) should not use typographical quotes around /viewlog. These should be straight code quotes instead, as used on page 273.

Jon Forrest  Jul 14, 2017  Jan 05, 2018
PDF
Page 268
3rd from last paragraph

"which read the data from the file and produce the large string:" ->
"which read the data from the file and produce the large string from the list:"

Note from the Author or Editor:
Add "from the list" to the end of the last sentence of the 3rd from last paragraph.

Jon Forrest  Jul 12, 2017  Jan 05, 2018
PDF
Page 222
1st paragraph

"every web request generates an HTTP status code response." ->
"every web request generates an HTTP status code in the response."

The way it was worded makes it sound like the response is just an HTTP status code. In reality it's an HTTP status code and other information.

Note from the Author or Editor:
At end of first paragraph, change "status code response" to "status code in its response".

Jon Forrest  Jul 11, 2017  Jan 05, 2018
PDF
Page 215
2nd line

(This is very minor)

"a HTML form" ->
"an HTML form"

Note: this error appears a bunch of times. If you search for "a HTML" you'll see what I mean.

Note from the Author or Editor:
Change "a HTML" to read "an HTML" on pages 226, 229, 234, 277, and 349. This brings these usages in line with the rest of the book.

Jon Forrest  Jul 11, 2017  Jan 05, 2018
PDF
Page 52
3rd paragraph

(Minor suggestion)

"The values associated with a key can be any object." ->
"The values associated with a key can be any type of object."

Note from the Author or Editor:
End of second paragraph under point 3. Change last line from:

"The values associated with a key can be any object."

to:

"The values associated with a key can be any object (of any type)."

Jon Forrest  Jul 03, 2017  Jan 05, 2018
PDF
Page 14
2nd to last paragraph

"When today is invoked, it returns a “time object,” "

There are two problems with this.

1) (Very trivial) The comma should be outside the quoted string.

2) today doesn't return a time object, e.g.

>>> from datetime import datetime
>>> type(datetime.today())
<class 'datetime.datetime'>

It looks like today returns a datetime object. The rest of this paragraph should be (slightly) modified to reflect this fact.

Note from the Author or Editor:
Change opening sentence for the largest paragraph on this page from:

"When today is invoked, it returns a “time object,” which..."

to:

"When today is invoked, it returns a “time object” (of type datetime.datetime), which..."

Note: the "datetime.datetime" bit should be shown in courier/code font.

Jon Forrest  Jul 02, 2017  Jan 05, 2018
PDF
Page 248
4th paragraph

(This is extremely minor)

You generally use italics for method names. However, in the 4th paragraph you say "forgetting to call close" without putting "close" in italics.

Note from the Author or Editor:
Change the use of "close" on fourth line of fourth paragraph to be in courier/code font as per the other uses on this page.

Jon Forrest  Jun 25, 2017  Jul 07, 2017
Printed, PDF, ePub
Page 255
screen shot

The {'a'} in the output in the screen shot should be {'x','y'} to maintain consistency with the three example searches from pages 252-253.

Note from the Author or Editor:
This reader is correct - some of the screenshots are out-of-sync with the text.

Note for Production: please contact me whenever the next update to the PDF is happening and I'll provide updated screenshots for pages 255, 256, and 258. On page 259, the third "<Request>" line at the top of page should end in {'x', 'y'} as opposed to {'a'}.

Rick Rakin  Jun 22, 2017  Jul 07, 2017
Printed, PDF, ePub, Mobi, , Other Digital Version
Page 207
Top of second last paragraph (opening sentence)

The opening sentence currently reads: "The route decorator lets you associate a URL web path with an existing Python function."

This should be changed to read: "The route decorator lets you associate a URL web path with the Python function which immediately follows the route decorator in your code."

In the same paragraph, the closing sentence currently reads: "The route decorator then waits for any output produced by the decorated function before returning the output to the server, which then returns it to the waiting web browser."

This should be changed to read: "The route decorator then waits for any data returned from the decorated function before returning it to the server, which then returns the data to the waiting web browser."

My thanks to reader Jon Forrest for bringing both of these to my attention. Jon's suggestions make it clearer what's going on here.

--Paul.

Paul Barry
Paul Barry
 
Jun 10, 2017  Jul 07, 2017
Printed, PDF, ePub
Page 139
1st paragraph

. . . display it in a easier-to-read format. . .
Should be:
. . . display it in an easier-to-read format. . .

Note from the Author or Editor:
Change "a easier" to "an easier" in first paragraph.

Rick Rakin  Jun 08, 2017  Jul 07, 2017
Printed, PDF, ePub
Page 237
3rd bullet point

On Pg 206 you say that __name__ is "the name of the currently active module. On Pg 237 you says that it's "the currently active namespace".
Although you say you'll go into more about the currently active namespace later, I suggest keeping the same wording on Pg 237 that you use on Pg 206. Since we don't know what a namespace is on Pg 237, there's no point to this change.

Note from the Author or Editor:
On page 237, in the Bullet Points box, third bullet point, change "active namespace" to read "active module".

Jon Forrest  Jun 08, 2017  Jul 07, 2017
PDF
Page 220
Last line

(This is very minor.)

The last line on the page shows a 304 status return code. The first time somebody visits the web page mentioned, this will be a 200 status return code. This should be mentioned.

Note from the Author or Editor:
At bottom of page, the second-last annotation reads "You request the HTML form...". This should be changed to read "You request the HTML form (which results in a 200 status code)..."

Jon Forrest  Jun 08, 2017  Jul 07, 2017
Printed, PDF, ePub
Page 213
3rd paragraph

(This is extremely minor. Sorry)

"but it’s not a absolute" ->
"but it’s not an absolute"

Note from the Author or Editor:
Change "a absolute" to "an absolute" in the sentence immediately above the "Create the HTML..." subheading.

Jon Forrest  Jun 08, 2017  Jul 07, 2017
Printed, PDF, ePub
Page 72
1st sentence

"When to comes to copying an existing list" -:
"When it comes to copying an existing list"

Note from the Author or Editor:
Change first use of "to" to "it" in first paragraph.

Jon Forrest  Jun 05, 2017  Jul 07, 2017
Printed, PDF, ePub
Page 17
2nd paragraph

"Take a closer look at the else statement"

There is no "else" statement in Python. Nor is there an "elif" statement (as mentioned lower on the page). The official Python tutorial calls them "parts" (https://docs.python.org/3/tutorial/controlflow.html). I didn't find a name for them in the official language definition.

Many online references make the same mistake.

Note from the Author or Editor:
The use of "else statement" in paragraph 2 should be "else part". (This reader is correct: "else" is part of the "if" statement). Same goes for use of "elif statements" at the end of the paragraph at the end of the first paragraph in the "Neither. Python spells it elif." subsection. It should read "elif parts". Both "else" and "elif" are part of the "if" statement, and are not statements in their own right.

Jon Forrest  Jun 02, 2017  Jul 07, 2017
Printed, PDF, ePub
Page 14
1st paragraph

You're inconsistent in your use of "line of code". On Pg 13 you say "The next three lines of code in our program" to refer to the three lines that make up the list assignment statement. Fine so far. But, on Pg 14 you say "Take another look at the third line of code:". Based on your first usage, the third line of code is actually the one that starts with "21, 23,". But your usage on Pg 14 refers to the assignment statement giving "right_this_minute" a value.

You need to distinguish between a "line of code", which is just a single line, and a "statement", which consists of one or more lines of code.

There are other examples of this inconsistency later in the book.

Note from the Author or Editor:
Noted. This is something that will be dealt with in the next major update. The reader is right: a single Python statement can span more than one line of code, and my usage needs to be clearer.

Jon Forrest  Jun 02, 2017 
Printed, PDF, ePub
Page 11
4th paragraph

(This is a minor issue)

"we are interested in the current time’s hours (%H) and minutes (%M) values" ->
"we are interested in the current time’s hour (%H) and minute (%M) values"

Note from the Author or Editor:
Middle paragraph of page 11, adjust as per this reader's suggestion.

Jon Forrest  Jun 02, 2017  Jul 07, 2017
PDF
Page 8
middle of page

I really like this book, but you commit a common sin, which is using a term before you explain it. You do this a lot in the 1st chapter. Examples of this are when you first use the terms "module", "attribute", and "method".

Note from the Author or Editor:
Noted for next major update, but: the assumption is that readers have programmed before so should have a familiarity with such terms (although I take the point that I could do a better job of it here).

Jon Forrest  Jun 02, 2017 
Printed, PDF
Page 90
6th paragraph

(This is extremely minor)

"in that there’s tags on the left" ->
"in that there are tags on the left"

Note from the Author or Editor:
On, man, I'm forever doing that (and my editor is going to be annoyed that she missed that one!). Thanks for pointing that out. We'll fix in in the next reprint. First paragraph after napkin images: "there's" should read "there are".

Jon Forrest  May 29, 2017  Jul 07, 2017
Printed, PDF
Page 458
Chapter 11's code

Chapter 11's Code first page has the same code as Chapter 11 3/4's first page.

As a result it has already :

- import of copy_current_request_context
- decorator @copy_current_request_context
- def log_request nested in def log_request

when all of those are described in forthcoming Chapter 11 3/4.

Note from the Author or Editor:
This reader is correct: the code shown at the end of Chapter 11 is the same as the code at the end of the next chapter, 11 3/4, and as such is presented too early for Chapter 11, as the material is not covered yet. The Chapter 11 code should mimic that from the ch11 folder of the online download. The correct code for 258 should *not* include any of the copy_current_request_context references - the updated code download reflects this. Chapter 11 3/4's code can be found in new ch11-3.4 folder included as part of the online download as of today (May 8, 2017). See python.itcarlow.ie/ed2/

Mateusz Muller  May 01, 2017  Jul 07, 2017
Printed, PDF
Page 459
Line 3 of Chapter 11's Code

There is unneeded closing bracket in "loq_request(request, results))".

Note from the Author or Editor:
Remove extra closing ")" from the end of the third line of code.

Mateusz Muller  Apr 27, 2017  Jul 07, 2017
Printed, PDF
Page 392
Second example of invoking search4letters function.

We have an example of seach4letters function to be invoked two different ways. By values or keyword arguments.

Example 1 is ok : search4letters(letters='xyz', phrase='galaxy')

But in Example 2 we have definition of function in fact :

"def search4letters(phrase:str, letters:str='aeiou') -> set"

Where invoking should look like :

search4letters('galaxy','xyz')



Note from the Author or Editor:
Change the annotation at top-right of this page to read: "Note how the interpreter matches up the arguments by name, no matter the order in which they are specified."

Mateusz Muller  Apr 19, 2017  Jul 07, 2017
Printed, PDF
Page 451
left annotation

Use opening (left) bracket instead of closing (right) bracket in

)i.e., the code within the “with” suite).

Note from the Author or Editor:
Confirmed. Please change the opening bracket/parens within the annotation at left of page to be (.

Jørgen W. Lang  Apr 13, 2017  Jul 07, 2017
Printed, PDF
Page 438
1st paragraph, last word

/search should be /search4

Note from the Author or Editor:
Last word of first paragraph should read: "/search4".

Jørgen W. Lang  Apr 12, 2017  Jul 07, 2017
Printed, PDF
Page 264
Exercise section

In Exercise steps descriptions there is:

"1.Save vsearch4log.py" where should be vsearch4web.py

Note from the Author or Editor:
Point 1 in box near top of page, "vsearch4log.py" should read "vsearch4web.py" on this page, as well as on page 259 (point 2 near bottom of page).

Mateusz Muller  Apr 11, 2017  Jul 07, 2017
Printed, PDF
Page 259
Exercise section

In Exercise steps descriptions there is:

"2.Save vsearch4log.py" where should be vsearch4web.py

Note from the Author or Editor:
Confirmed. See note for errata on page 264.

Mateusz Muller  Apr 11, 2017  Jul 07, 2017
Printed, PDF
Page 246
Result of print(chore) function

Very small mistake on page 246 where results for called function :

for chore in tasks:
print(chore)

we can find "File tax return.", where should be "Prepare tax return."

Note from the Author or Editor:
Change "File tax return." to "Prepare tax return." (at bottom of page) as per text written to the todos.txt file on the previous page.

Mateusz Muller  Apr 11, 2017  Jul 07, 2017
PDF
Page 390
2nd annotation on the right

Missing right bracket in annotation after "list.".

Should be:

Many arguments (which, in this example, are all numbers, but could be anything: numbers, strings, booleans, list.)

Note from the Author or Editor:
Add the closing ) to the annotation half-way down the page.

Jørgen W. Lang  Apr 07, 2017  Jul 07, 2017
Printed, PDF
Page 171
Example with keyword assignment.

On Page 171 there is example with argument keyword assignment use for invoking function.

Below

search4letters(letters='xyz', phrase='galaxy')

def search4letters(phrase:str, letters:str='aeiou') -> set

There is information, that result of the function is y and z, which is mistake as result should be y and x.

Note from the Author or Editor:
The first sentence of the last paragraph on this page should end as follows: "... a set containing the letters x and y."

Mateusz Muller  Mar 31, 2017  Jul 07, 2017
Printed, PDF
Page 358
First line of text below heading

"It’s now time to return to the questions first posed in Chapter 7:"

should actually be

It’s now time to return to the questions first posed in Chapter 6:

## (on page 244)

Note from the Author or Editor:
On page 358: change the first sentence to read: "It’s now time to return to the questions first posed at the end of Chapter 6:".

Also, on page 359: change first half of first sentence to read: "Let’s take our data questions one by one, ..."

Jørgen W. Lang  Mar 29, 2017  Jul 07, 2017
Printed, PDF
Page 341
1. para, 2nd line

"Here’s the code from the last chapter, rewritten to use a with statement, which itself…"

refers to Ch 8, but the code presented below was created in Ch 7.

Suggested correction:
"Here’s the code from chapter 7, rewritten to use a with statement, which itself…"

Note from the Author or Editor:
Change second sentence to read: "Here's the code from Chapter 7, rewritten..."

Jørgen W. Lang  Mar 28, 2017  Jul 07, 2017
Printed, PDF
Page 313
bottom example, top right annotation

"Create another new object, and assign it to an object called “c”."

Should probably be:

Create another new object, and assign it to a variable called “c”.

Note from the Author or Editor:
Yes, change the third from bottom annotation on the RHS of page to replace "object called c" to read "variable called c".

Jørgen W. Lang  Mar 23, 2017  Jul 07, 2017
Printed, PDF
Page 258
1st paragraph, last sentence

Current text:
"…then call escape on the string returned from calling the *join* method:"

But there is no *join* method in the code. This should probably be:
"…then call escape on the string returned from calling the *log.read()* method:"

Note from the Author or Editor:
This issue presents on a number of pages.

Page 254: Referring to paragraph 5 after the with open('vsearch.log') as log line of code. The end of the first sentence should read: "...need to read all the data from the file." That is, the word "lines" should be "data".

Also on page 254: The last annotation on the right is wrong. It should read: 'Take the data in contents and return it.' (with 'contents' shown in code font).

Page 258: The end of the first paragraph on this page should read: "...then call escape on the string in contents:" (with 'escape' and 'contents' shown in code font).

Page 271 and 272: The code for view_the_log() is incorrect. It should match the code on page 258.

Page 271: After the code, the exercise states: "This code reads the data from the log file into a list of strings." and it should read: "This code reads the data from the log file into a string."

Jørgen W. Lang  Mar 16, 2017  Jul 07, 2017
Printed, PDF
Page 267
last paragraph

The first sentence states that the logged data is read as a list of strings thanks to the readline method. But this method has been never used before. The view_the_log function shown on page 258 uses the read method and returns a single string.

Note from the Author or Editor:
Please change the opening sentance to the last paragraph on this page to read:

"When the logged data is read from the vsearch.log file, it can arrive in your code as a list of strings if you use the readlines method (as readlines converts a file's text to a list of strings on input)."

Pavlo Gotsonoga  Mar 02, 2017  Jul 07, 2017
Printed, PDF
Page 430
first paragraph second line

As written
“interpreters, internals …”
As intended, the internals owned by the interpreter:
“interpreter’s internals …”

Thanks a well written and thought out book,
regards, Chris

Note from the Author or Editor:
Second line, first paragraph: "interpreters, internals" should read: "interpreter's internals".

Chris Clark  Feb 23, 2017  Jul 07, 2017
Printed, PDF
Page 422
third paragraph ninth sentence

page 422 third paragraph ninth sentence
As written
“... parameterized SQL strings (with all those ? …”
perhaps as intended
“... parameterized SQL strings (with all those %s …”
For me, SQL prepared statements are associated with the question mark.

Thanks for a very useful and enjoyable book,
warm regards, Chris

Note from the Author or Editor:
Yes, thanks: in point 3 "all those ? placeholders" should read "all those %s placeholders".

Chris Clark  Feb 22, 2017  Jul 07, 2017
Printed, PDF
Page 189
5th paragraph, start of sentence

As written,
"One more, ..."
I believe
"Once more, ..."
is intended.

Thanks for a very useful and well thought out book.

Note from the Author or Editor:
Change "One more" to "Once more" at start of second paragraph in "Recalling our code" section.

chrsclrk  Feb 06, 2017  Jul 07, 2017
Printed, PDF
Page 209-210
In the exercise text

The phrase "life, the universe, and everything" should NOT have a trailing '!'. The code and subsequent screenshots are correct - the description of what the reader is to do (and the phrase to use) on page 209 and 210 incorrectly includes the '!' symbol at the end of the string.

Paul Barry
Paul Barry
 
Jan 24, 2017  Jul 07, 2017
Printed, PDF
Page 475
Top of code (the first import line).

The continued importation of the "escape" function from Flask is no longer technically required here. It's OK that it's still here, but - if for no other reason than to tidy things up - it should be removed from this code listing.

Note: my thanks to eagle-eyed reader Sajjad Taheri who very kindly took the time to email all of these errata which I've inserted into the list today (dated: Jan 23, 2017).

Paul Barry
Paul Barry
 
Jan 23, 2017  Jul 07, 2017
Printed, PDF
Page 474
Bottom of third paragraph from bottom of page

On the last line "matter now long it takes" should read "matter how long it takes".

Paul Barry
Paul Barry
 
Jan 23, 2017  Jul 07, 2017
Printed, PDF
Page 444
Annotation 1

This annotation (#1) should read: Create a new class called “ConnectionError” that inherits from the “Exception” class. Note how the inherited-from class is specified within the parentheses to "ConnectionError".

Paul Barry
Paul Barry
 
Jan 23, 2017  Jul 07, 2017
Printed, PDF
Page 310
The large note to the right of the page

It should read "...lets you..." not "...lets your..."

Paul Barry
Paul Barry
 
Jan 23, 2017  Jul 07, 2017
PDF
Page 285
The paragraph immediately above the screenshot

The embedded hyperlink for dev.mysql.com (at the top of the paragraph) does not include the entire URL, so your browser takes you to the mysql.com site, but not the correct page (/downloads/connector/python).

Paul Barry
Paul Barry
 
Jan 23, 2017  Jul 07, 2017
Printed, PDF
Page 268
Code near bottom of page

The last three lines of code shown for view_the_log are not identical to the previously shown version (way back on page 258). Specifically, the last line is slightly different. The surrounding text discusses this change, but the last line of code should be highlighted better than it is on this page.

Paul Barry
Paul Barry
 
Jan 23, 2017  Jul 07, 2017
Printed, PDF
Page 218
Under point 3, middle of page.

The value associated with 'the_title' key is missing a closing single quote after "web!". Note: the code at the bottom of the page is correct.

Paul Barry
Paul Barry
 
Jan 23, 2017  Jul 07, 2017
PDF
Page 189
The large note to the right of the page

The URL for pytest does not hyperlink to the correct page and needs to be updated in the PDF.

Note from the Author or Editor:
should go to https://docs.pytest.org/en/latest/

Paul Barry
Paul Barry
 
Jan 23, 2017  Jul 07, 2017
Printed
Page 88
1st illustration

The word "Paranoid" is misspelled in the illustration. This throws the indexing off so that the statement in the final paragraph on the page is contradicted by the indexes in the illustration.

Note from the Author or Editor:
The first illustration at the top of the page has an extra 'r' in index position 16, which invalidates the diagram. Note to production: when you come to apply this fix, email me and I'll provide an updated illustration.

John D Ogden  Jan 17, 2017  Jul 07, 2017
PDF
Page 116
1st line of code, after the 3rd paragraph

hfpy [2017-01-06],

i got the following error when running

>>> fruits
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'fruits' is not defined

the dictionary should be initialised before enumerating. the first line of key should be.

fruits = {}

Note from the Author or Editor:
The first line of code in the middle of this page should read:

>>> fruits = {}

This initializes the dictionary before first use.

Anonymous  Jan 14, 2017  Jul 07, 2017
PDF
Page 182
under "Step 3 on UNIX-like OSes?" near the bottom of page, at the end of the first line of the first paragraph of text

"dict" should be "dist"

O'Reilly Media
 
Jan 06, 2017  Jul 07, 2017
Printed, PDF
Page 345
3rd paragraph

exec_type should be "exc_type". Shown correctly in the example code.

Note from the Author or Editor:
Yes, "exec_type" should be "exc_type" in middle of third paragraph.

jlcooke  Dec 23, 2016  Jan 06, 2017
Printed, PDF, ePub, Mobi,
Page 268
return statement in last example

In prior examples changes to code have been highlighted in a light-blue. The last example of the return statement for this function I could find is on page 258: "return escape(contents)".

My question is: did I miss where I should have changed the statement to "return escape(''.join(contents))" or should this statement be highlighted.

I suspect the join example should be inserted somewhere earlier (or I missed it) because I could not get the early examples of log_request() to work (p. 261). I kept getting an exception when attempting to print (ImmutableMultiDict is not a string). I corrected it with a "str(req.form)". But seeing this page makes me think you meant to supply "join" earlier.

Note from the Author or Editor:
Yes, I should be highlighting that return statement in blue (the last line of code on page 268) to note that it has changed. The very next paragraph of text does discuss it (for what it's worth).

jlcooke  Dec 22, 2016  Jan 06, 2017
Chapter 7 "Consider what you're trying to reuse" second paragraph 1st sentence

It’s should be clear......

should be

It should be clear......

Anonymous  Dec 12, 2016  Jan 06, 2017
PDF
Page 125
Lower right page. "Comment" typeface.

"Python conversts" should be "Python converts"

jlcooke  Dec 11, 2016  Jan 06, 2017
Printed
Page 59
1st paragraph

Did you mean to change the spelling of the example from a few pages ago to "Millyways"? It was: "Milliways" a few pages ago and that changes the number of vowels in the word (unless you are setting up a "sometimes 'y'" scenario).

Note from the Author or Editor:
Yes, that's a typo - should be "Milliways".

jlcooke  Dec 09, 2016  Jan 06, 2017
Chapter 5 1st paragraph 1st sentence

There are no page numbers for the Safari Books online.

(even though there’s still lots to of Python to learn)

Should be

(even though there’s still lots of Python to learn)

Anonymous  Dec 01, 2016  Jan 06, 2017
PDF
Page 18
2nd paragraph

"jsut"

Rachel Vishnepolsky  Jan 03, 2016  Nov 04, 2016
PDF
Page 8
2nd paragraph

"enture stndard"

Rachel Vishnepolsky  Jan 03, 2016  Nov 04, 2016