Update: If you are interested in Python 3 you might also like my book Porting to Python 3 – An in-depth guide.

In the python-incompatibility project I’ve added loads of code that works under 2.5 but does not work under Python 3.0. I’ve also added code on how to re-write the code so that it will run under both 2.6 and 3.0.

Quite a lot of time, the rewritten code will run not only under 2.6 and 3.0, but also under 2.5! This may be surprising, but the reason is that you in 2.x is able to do a lot of bad things that you can’t do in 3.0.

One example is using the keys of a dictionary as a list. For example, this code is valid in 2.x:

d = {'key1': 'value1', 'key2': 'value2', 'key3': 'value3', } d.values()[1]

But doing that is a bad idea. The keys of a dictionary isn’t sorted, so you don’t know which one you get back. Of course, if you are going through all the keys, that’s OK, but that would mean you are doing some sort of basic newbie mistake, like

for i in len(d.keys()): key = d.keys()[i]

When you should be doing

for key in d.keys():

Now, in Python 3 you simply cannot slice the keys of a dictionary, because .keys() doesn’t return a list, but a view, which isn’t sliceable. So, these kinds of bad programming can’t happen in Python 3. Or, well, they can, but you need to also explicitly convert keys() to a list, so it’s unlikely you do it by mistake, which can happen under 2.5, where one person can start slicing a list without noticing that it comes from a dictionary further up in code that somebody else wrote. So in 3.0 you have to intentionally create bad code in situations where it could happen by mistake in 2.x.

I like Python 3. Python 2 rocks. Python 3 is metal!

– An in-depth guide