While my Python 3 posts seemed to stretch for pages and pages with differences, there actually aren’t very many changes at all. Most of that space is taken up by the code outputs (which often had only minor changes) and unchanged code (that had to be there for context). In fact, while the book is about 300 pages long, just a handful of changes are needed to get the whole of the code in the book to run in Python 3. Those changes (in alphabetical order by topic) are below. Check them out if you’re having trouble with your other Python 2.7 code:
Links to the Python 3 updates for each of the Projects:
Project 2, Project 3, Project 4, Project 5, Project 6, Project 7, Project 8, Project 9, Project 10.
class
In Python 3, classes inherit from object automatically, so you don’t need (object) in the first line of the class definition. It’s not an error, but it is superfluous.
# Python 2.7 >>> class AddressEntry(object): """ AddressEntry instances hold and manage details of a person """ pass # Python 3 >>> class AddressEntry: # note: no (object) """ AddressEntry instances hold and manage details of a person """ pass
Floating point division
Python 2 code in the book will work with Python 3. Some changes to floating point is now automatic in Python 3, so the code to change a number into floating point (eg float(2)) is unnecessary.
import cPickle as pickle
Python 3 uses cPickle by default, so replace import cPickle as pickle by just import pickle. If you try to import cPickle, you’ll get an error.
open
In Python 3 open() has the same syntax as in Python 2.7, but uses a different way to get data out of the file and into your hands. As a practical matter this means that some Python 2.7 code will sometimes cause problems when run in Python 3. If you run into such a problem (open code that works in Python 2.7 but fails in Python 3), the first thing to try is to add the binary modifier – you’ll need it when reading and writing pickle files for instance. So, instead of ‘r’ or ‘w’ for read and write use ‘rb’ or ‘wb’.
#Python2.7 >>> import pickle >>> FILENAME = "p4k_test.pickle" >>> dummy_list = [x*2 for x in range(10)] >>> with open(FILENAME,'w') as file_object: #now dump it! pickle.dump(dummy_list,file_object) >>> # open the raw file to look at what was written >>> with open(FILENAME,'r') as file_object: # change w to r!!! print(file_object.read()) #Python3 >>> import pickle >>> FILENAME = "p4k_test.pickle" >>> dummy_list = [x*2 for x in range(10)] >>> with open(FILENAME,'wb') as file_object: #### note: 'wb' not 'w' pickle.dump(dummy_list,file_object) >>> # open the raw file to look at what was written >>> with open(FILENAME,'rb') as file_object: ##### note 'rb' not 'r' print(file_object.read())
Print – mostly the same, since I used Python 3 print syntax in the book. There is an issue with the print continuation character (trailing comma). That needs to be replaced by an end parameter:
#Python 2.7 code: >>> my_message = "Hello World!" >>> while True: ... print(my_message), #<- notice the comma at the end ... #Python 3 >>> my_message = 'Hello World!' >>> while True: ... print(my_message, end="") ...
If you’re using Python 2.7 code that’s not in my book, it might look like this:
#Python 2.7 code: >>> print "Hello World"
To make this work in Python 3, you put brackets around what’s to be printed:
#Python 3 >>> print("Hello World")
raw_input v input
In Python 3 replace raw_input by input wherever you see it. Literally, input is simply a new name for raw_input.
Range vs xrange
The book uses range in anticipation of upgrading to Python 3, so mostly the code will work without changes! If you have code that uses xrange, just rename it to range and all should be well.
In one case the code assumed that the output of range is a list (which is is in Python 2.7, but not in Python 3). The code’s syntax was correct, but led to a logical error. That was corrected by choosing a way to test for the end of the loop that didn’t assume a list was involved.