The fascinating quest of figuring out the difference between.

Let’s start with the background of this race for the truth.
In the first week of our boot camp training (winter 2020), we got the first team task to make a presentation “within 20 minutes” on one of 12 topics. No one attached much importance to this: there were still four weeks left before the day of the presentation. But in two days the conditions had changed: me and my teammate Yoav Vollansky should speak about the differences between Python 2 and Python 3 to the audience already in 3 days.A google search yielded us many articles and reviews on our topic, and of course I am writing this post with a link to them.
So when did Python 2 fade start?
In December 2008, Python released version 3.0. This version was mainly released to fix problems that exist in Python 2. The nature of these changes is such that Python 3 was incompatible with Python 2. It is backward incompatible. Some features of Python 3 have been backported to Python 2.x versions to make the migration process easy in Python 3.
As a result, for any organization that held the Python 2.x version, migrating their project to 3.x needed lots of changes. These changes related more than to projects and applications. They affected all the libraries that form part of the Python ecosystem.
Python 2 made the code development process easier than earlier versions. It implemented technical details of Python Enhancement Proposal (PEP). Python 2.7 (last version in 2.x ) is no longer under development and since 2020 discontinued:

Why is this upgrade so significant (and also problematic)?
Timeline
- Python appeared in the 80s
- Python 2 appeared in 2000
- Python 3 appeared in 2008
Introduced in Python 2
- list comprehension
- garbage collection system
- an open source approach / community-backed etc.
New in Python 3
- too much for being able to just call it Python 2.8 … as we shall see…
The changes were so enormous in Python 3 (in comparison to Python 2) that Python 3 is backward incompatible! (as opposed to natural upgrades). In the long run, a lot of time and money spent proceeding with the modernization of tremendous amounts of codes and libraries code rely on.
So there’s a newer, better version. Great! Why the heck do we need to waste time talking about the old one?
What the world thinks?

On average, for the last five years, about 1/3 of Google searches are about Python 2!
Maybe, these cyclical drops in searches can give us the answer?
I don’t think so, but everything is temporary in our world. Python versions are not an exclusion as well.
How come Python 2 did not go extinct?
- Some tools that are still being used today, especially in the DevOps domain, are Python 2 coded.
- Some companies still hold/maintain old codebase, in general.
- Some libraries you would need are Python 2.Main difference:
1. Already seen the print statment which was changed to a function
- In Python 2.0, the print-syntax is treated as a statement rather than a function.
- When
print()is a function — as with any function we can do this:

Some other method’s funcionalities in Python 3 impossible in Python 2:

Now let’s try something crazy. What do you think? Will it work?

2. Division in Python 2 would always return an INT, in Python 3 it returns a FLOAT:

In Python2, we have no frequent in Python 3 and a good readable short version of the String.format() .
3. Unicode: in Python 3 we have Unicode strings, and two byte classes — byte and bytearray.

In Python 2, we can’t convert a string into a byte. We can convert string there only into a byte array by using a separate bytearray() function (as well as unicode() function). By definition, in Python 2, any text will have a String type.
4. The xrange() function
The usage of xrange() is frequent in Python 2 for creating an iterable object, e.g., in a for-loop or list/set-dictionary-comprehension. The behavior was quite similar to a generator (i.e., “lazy evaluation”), but here the xrange-iterable is not exhaustible – meaning, you could iterate over it infinitely.
The xrange() is generally faster if you have to iterate over it only once (e.g., in a for-loop).
In Python 3, the range() was implemented like the xrange() function so that a dedicated xrange() function does not exist anymore (xrange() raises a NameError in Python 3).

xrange() function in Python 2 and Python 3If we need to iterate over the same sequence multiple times, we preferrange() as range provides a static list.
xrange() reconstructs the sequence every time. xrange()doesn’t support slices and other list methods.
The advantage of xrange() — saves memory when the task is to iterate in a wide range.
Python 3 offersrange() function to perform iterations while, In Python 2, the xrange() is used for iterations.
In Python2 range() returns a list of numbers while xrange() returns an object
5. Error Handling
There is a small change in error handling in both versions. In Python 3.x, required the “as” keyword.
Exceptions in Python 3 are enclosed in parenthesis while, in Python 2 — in notations.
The “raise” statement in Python 2 was designed at a time when exceptions weren’t classes. Type of an Exception, value, and traceback components were three separate objects.
In Python 3, one single object includes all information about an exception. This object used with raise must be an instance of BaseException, while Python 2 also allowed old-style classes.

Similarly, Python 3 bans catching non-exception classes in the except statement.
Exception Chaining Python 3 introduced exception chaining by default. In Python 2, when an exception occurs in a library referenced by the main Python program, by default, the details of that exception would not be visible in a traceback. In Python 3, the traceback shows full details of exceptions, both those thrown by the main program, by referenced libraries.
Any internals of your code or runtime behavior (when exposed to the user) creates a security risk. Although Exception chaining is convenient for debugging, it reveals much more information to a potential attacker, who can run a traceback to see how the software reacts to errors.
It is possible to disable chained exceptions in Python 3 if you believe the risk outweighs the benefits.
So what does the Python standard library provide to manage the incompatibility between Python 2 and 3?
The following are some modules that we can use:
builtins: to create wrappers around built-in functions, builtins are useful.future_builtins: function map and filter in Python 2 behave differently than in Python 3.- To get Python 3 behavior, use from
future_builtins import map, filter __future__: in Python 2, to useprint()only as a function, usefrom __future__ import print_function.2to3: To convert Python 2 code to Python 3, this standard library can be used. It applies a series a fixers to do the conversion. It’s based onlib2to3library, which can be used to add custom fixers.- Python
Converteris online conversion tool based on2to3:http://www.pythonconverter.com/ - There is a cheatsheet that gives examples of writing compatible code: http://python-future.org/compatible_idioms.html
You read a lot in this article. It gives a deeper understanding of the global Python language conception and its development history.
Code link: google collab