Python 2 vs 3

Python 3 was released to fix problems present in Python 2. The nature of these changes meant that Python 3 was incompatible with Python 2. It also meant that Python 3 did not carry forward the problems of Python 2. Some aspects of Python 3 have been backported to Python 2.6 and 2.7 to make the migration to Python 3 easier.

Python 2 was supposed to be retired in 2015 but slow adoption of Python 3 led to an extended deadline of 2020. Python 2.7 will receive updates till 2020 for security and bug fixes only.

As of February 2018, it's seen on Python 3 Readiness that 348 of 360 most downloaded packages from PyPI already support Python 3.

It's expected that if ever there should be a Python 4, it will be compatible with Python 3.


  • What were the main issues with Python 2?

    A str object could represent either text or binary data. This easily results in bugs because developers often don't use unicode type for text. Python 3 solves this by making all str Unicode and having bytes type to handle binary data. It's explicit and unambiguous. To support string literals involving non-ASCII characters, making Unicode as default is a good thing.

    When functions are treated as objects in Python and can take arguments, print is an unnecessary exception. It's a statement in Python 2 but making it a function would be make it more flexible.

    Division that should result in a float instead does truncation and results in an int. Python 2 needed extra functions/methods to minimize RAM usage but Python 3 does lazy evaluation by default. Although Python is strongly typed, Python 2 permits strange comparisons: None < 3 < "2".

    Nick Coghlan provides a detailed discussion of why Python 3 was defined in a backwards incompatible manner.

  • I am new to Python. Should I learn Python 2 or Python 3?

    Python 3 fixes many of the problems that are present in Python 2. Python 3 is also the future of the language since Python 2 will be retired in 2020. It's therefore recommended that beginners learn Python 3. Moreover, if you're going to write new code, Python 3 is the one to choose. Eevee's blog article gives a detailed explanation of all the good things in Python 3.

    If you've to maintain legacy Python 2 code, it's still best to learn Python the right way from Python 3. Then you can study the differences between Python 2 and 3. The point is that the two versions are much more similar than different.

  • What features of Python 3 have been backported to Python 2.7?

    Backporting has been done mainly to aid in the eventual migration of Python 2 code to Python 3. A list of backports is documented in the official Python Docs and explained briefly in Eevee's blog.

    As an example, bytes and bytearray are part of Python 3.x but they were backported to 2.6 but with very different semantics. In Python 2, bytes is really an alias of str. The purpose was really to aid converters such as 2to3.

  • What are the differences between Python 2 and Python 3 for data types?
    Handling of strings and bytes. Source: Adapted from Hornick and Yoder, 2018, slide 3.
    Handling of strings and bytes. Source: Adapted from Hornick and Yoder, 2018, slide 3.

    Following is a summary of key differences:

    Python 2.XPython 3.X
    There's ASCII str type and unicode type, but no separate type to handle bytes of dataAll strings (str) are Unicode strings; two byte classes are introduced: bytes and bytearray
    Two types of integers: C-based integers (int) and Python long integer (long)All integers are long but referred to by the int type
    Return type of division is int if operands are integers: 5 / 4 gives 1; 4 / 2 gives 2Return type of division is float even if operands or result are integers: 5 / 4 gives 1.25; 4 / 2 gives 2.0
    round(16.5) returns a float of value 16.0round(16.5) returns an int of value 16
    Unorderable types can be comparedComparison of unorderable types raises a TypeError
  • What are the other differences between Python 2 and Python 3?
    How user input differs between Python 2 and 3. Source: Klein, 2018.
    How user input differs between Python 2 and 3. Source: Klein, 2018.

    Following is a summary of key differences:

    Python 2.XPython 3.X
    print is a statement: print "Hello World!"print() is a built-in function: print("Hello World!")
    range() returns a list of numbers while xrange() returns an object for lazy evaluationrange() returns an object for lazy evaluation similar to Python 2 xrange(); and range() method __contains__ speeds up lookups
    Functions/methods map(), filter(), zip(), dict.items(), dict.keys(), dict.values() return listsThese function/methods return objects for lazy evaluation
    raw_input() returns input as str and input() evaluates the input as a Python expressioninput() will return a string similar to Python 2 raw_input()
    Raising exceptions: raise IOError("file error") or raise IOError, "file error"Raising exceptions: raise IOError("file error")
    Handling exceptions: except NameError, err: or except (TypeError, NameError), err:Handling exceptions: except NameError as err or except (TypeError, NameError) as err
    On generators, a method or function call: or next(g)On generators, only a function call: next(g)
    Loop variables in a comprehension leak to global namespaceLoop variables are limited in scope to the comprehension
  • 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 is useful.
    • future_builtins: Function map and filter in Python 2 behave differently than in Python 3. To get Python 3 behaviour, use from future_builtins import map, filter.
    • __future__: In Python 2, to use print() only as a function, use from __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 on lib2to3 library, which can be used to add custom fixers. Python Converter is online conversion tool based on 2to3.
  • I have a legacy Python 2 codebase but would like to start supporting Python 3 as well. What can I do?

    There are a few approaches that developers can take depending on the need:

    • modernize: This is useful when you want to partially support both 2 and 3 with the goal of eventually porting to Python 3.
    • future: This enables either Python 2 or 3 code to be used across both versions. It comes with scripts futurize and pasteurize for 2-to-3 and 3-to-2 conversions respectively so that a single codebase can be used. It's supported for versions 2.6+ and 3.3+. There is a cheatsheet that gives examples of writing compatible code.
    • six: This wraps over the differences between 2 and 3 without modifying code. This means the code can run on both versions.

    It's recommended to drop support for Python 2.6 and older if possible. If legacy code must be maintained, one can opt for commercial services such as from ActiveState.

    Tools such as pylint, caniusepython3 and tox can help in checking or maintaining compatibility. Developers can also refer to a cheatsheet on writing compatible code; or get familiar with common migration problems.



Python 2.6 is released. The development of this release is synchronized with that of Python 3.0. Thus, Python 2.6 incorporates some changes that are part of Python 3.0. This backporting is expected to make way for easier migration of Python 2.6+ code to Python 3.x. Module future_builtins has 3.0 semantics.


Python 3.0 is released. It simplifies some of the unwieldy syntax that was in Python 2.x. It's not backward compatible with Python 2.x and hence it's release is seen as controversial. However, Python 3.x is the future of the language. Python 3.0 itself is deemed a failure due to slow IO.


Python 3.1 is released and it supercedes Python 3.0 that was unusable.


Python 2.7 is released. It includes some features introduced in Python 3.1. Python 2.7.x releases will receive bug fixes as well as backports from Python 3.x to make it easier in future to migrate that code to Python 3. It's the last 2.x release (there won't be a 2.8 release). It's expected to be retired in April 2020, implying that it will be maintained for 10 years since it's initial release.


Python 3.2 is released. A year later, it's seen that with this release Python 3 gains traction.


Python 3.3 reinstates the redundant syntax for Unicode string: u'hello'. This is done to enable easier migration from 2 to 3.


Python 2.6 reaches end of life and at least one expert recommends (in 2016) that developers should move to 2.7 if moving to 3.x is not an option.


Jake VanderPlas states that the scientific community should adopt Python 3 thanks to tools such as six and future. In 2013, VanderPlas had noted that moving to Python 3 was impossible (back then). In November, popular Python author Zed Shaw publishes a scathing article against Python 3. A day later, blogger named Eevee publishes a detailed rebuttal.

In 2017, Python 3 adoption is at 75% overall. Source: JetBrains 2017.
In 2017, Python 3 adoption is at 75% overall. Source: JetBrains 2017.

A Python Developers Survey towards the end of 2017 done by JetBrains finds that 75% of respondents use Python 3. In the domain of data science, adoption is higher at 80%.


The last major version of Python 2.7 is expected to be released in April. Following this, Python 3 will be the only one supported for bugs and security fixes.

Sample Code

  • # Division
    # Python 2.x
    print 3 / 2 # 1
    # Python 3.x
    print(3 / 2) # 1.5
    # Python 2.x and 3.x
    from __future__ import division
    print(3 / 2) # 1.5
    # Types int and long: there's only int in Python 3.x
    # Python 2.x
    bigone = 12345678901234567890
    print(type(bigone)) # long
    # Python 3.x
    bigone = 12345678901234567890
    print(type(bigone)) # int
    # Strings are in Unicode by default in Python 3.x
    # Python 2.x
    russian_hello = 'Здравствуйте'
    erh = russian_hello.encode('utf-8') # error since russian_hello is in ASCII
    russian_hello = u'Здравствуйте' # in Unicode
    erh = russian_hello.encode('utf-8')
    type(erh) # str
    # Python 3.x
    russian_hello = 'Здравствуйте'
    erh = russian_hello.encode('utf-8')
    type(erh) # bytes
    # Source:
    # Type str in Python 3.x is Unicode by default
    # Python 2.x
    print "café" + u"hello" # UnicodeDecodeError
    # Python 3.x
    print("café" + u"hello")
    # Source:
    # Python 2.x
    # Will print h and i
    for i in bytes(b"hi"):
        print(i, type(i))
    # Python 3.x
    # Will print 104 and 105
    for i in bytes(b"hi"):
        print(i, type(i))
    # Two prints on the same line
    # Python 2.x (trailing comma)
    print "hello", ; print("world")
    # Python 3.x (use end argument)
    print("hello", end=" "); print("world")
    # Comprehension loop variable (leaks in Python 2.x)
    # Python 2.x
    del x
    [x*x for x in xrange(10)]
    print x # prints 9
    # Python 3.x
    del x
    [x*x for x in range(10)]
    print(x) # throws an error 
    # Comparison of mismatched types
    # Python 2.x
    print "3" > 4 # True since ord("3") = 51 > 4
    # Python 3.x
    print("3" > 4) # TypeError
    # Lazy evaluation in Python 3.x
    # Python 2.x
    import string
    pairs = zip(string.ascii_uppercase, string.ascii_lowercase) # list of tuples
    # Python 3.x
    import string
    pairs = zip(string.ascii_uppercase, string.ascii_lowercase) # zip object
    next(pairs) # return first tuple on demand
    # print the rest within a for loop
    for pair in pairs:
    # Calling the base class method via super() is simpler in Python 3.x
    # Python 2.x
    class Cat(Animal):
        def __init__(self, x, y):
            super(Cat, self).__init__(x, y)
    # Python 3.x
    class Cat(Animal):
        def __init__(self, x, y):
            super().__init__(x, y)


  1. Brandl, Georg. 2006. "PEP 3105 -- Make print a function." November 19. Accessed 2018-02-20.
  2. Cannon, Brett. 2015. "Why Python 3 exists." Tall, Snarky Canadian. December 16. Accessed 2018-02-19.
  3. Cannon, Brett. 2018. "Porting Python 2 Code to Python 3." Python HOWTOs. Accessed 2018-02-19.
  4. Coghlan, Nick. 2012. "Python 3 Q & A." Nick Coghlan's Python Notes. June 29. Updated 2017-04-22. Accessed 2018-02-19.
  5. Eevee. 2016a. "Python FAQ: How do I port to Python 3?" Fuzzy Notepad Blog. July 31. Accessed 2018-02-20.
  6. Eevee. 2016b. "A Rebuttal For Python 3." Fuzzy Notepad Blog. November 23. Accessed 2018-02-20.
  7. Greg H. 2019. "Python 2 series to be retired by April 2020." Blog, Python Software Foundation, December 20. Accessed 2020-01-02.
  8. Hall, Aaron. 2014. "Catch multiple exceptions in one line (except block)." StackOverflow. June 21. Accessed 2018-02-20.
  9. Hornick, Mark L. and Josiah Yoder. 2018. "CS2910 Week 2, Class 1." SlidePlayer. Accessed 2018-02-20.
  10. Jeffr. 2017. "Python 3 vs Python 2: It’s Different This Time." January 26. Accessed 2018-02-20.
  11. JetBrains. 2017. "Python Developers Survey 2017 Results." Accessed 2018-05-08.
  12. Kearney, Derrick and Michael Herman. 2018. "First Steps With Python." Real Python. Accessed 2018-02-20.
  13. Klein, Bernd. 2018. "Input from Keyboard." Python Course. Accessed 2018-02-20.
  14. Kuchling, A. M. 2018a. "What’s New in Python 2.6." Python Docs, V3.6.4. Accessed 2018-02-18.
  15. Kuchling, A. M. 2018b. "What’s New in Python 2.7." Python Docs, V3.6.4. Accessed 2018-02-18.
  16. Python Clock. 2018. "Python 2.7 will retire in..." Accessed 2018-02-18.
  17. Python Docs. 2018a. "2to3 - Automated Python 2 to 3 code translation." V3.6.4. Retrieved 2018-02-19.
  18. Python Docs. 2018b. "future_builtins — Python 3 builtins." V2.7.14. February 3. Accessed 2018-02-19.
  19. Python Docs. 2018c. "builtins — Built-in objects." V3.6.4. Retrieved 2018-02-19.
  20. Python-Future. 2017. "Easy, clean, reliable Python 2/3 compatibility." Python-Future, Python Charmers Pty Ltd, Australia. May 6. Accessed 2018-02-19.
  21. Python-Modernize. 2014. "Python-Modernize." Read the Docs. October 5. Accessed 2018-02-19.
  22. Python3 Statement. 2018. "Moving to require Python 3." February 14. Accessed 2018-02-20.
  23. Raschka, Sebastian. 2014. "The key differences between Python 2.7.x and Python 3.x with examples." June 1. Accessed 2018-02-20.
  24. Shaw, Zed. 2016. "The Case Against Python 3 (For Now)." Learn Python the Hard Way. November 22. Accessed 2018-02-20.
  25. Six Docs. 2015. "Six: Python 2 and 3 Compatibility Library." V1.10.0. Accessed 2018-02-19.
  26. VanderPlas, Jake. 2013. "Will Scientists Ever Move to Python 3?" Pythonic Perambulations. January 3. Updated March 2016. Accessed 2018-02-20.
  27. Wikipedia. 2018. "History of Python." January 25. Accessed 2018-02-20.
  28. Wood, Sam. 2015. "A Brief History of Python." October 14. Accessed 2018-02-18.
  29. chhantyal. 2018. "Python 3 Readiness." Accessed 2018-02-20.
  30. nosklo. 2011. "The bytes type in python 2.7 and PEP-358." StackOverflow. May 5. Accessed 2018-02-20.

Further Reading

  1. Cannon, Brett. 2018. "Porting Python 2 Code to Python 3." Python HOWTOs. Accessed 2018-02-19.
  2. Regebro, Lennart. 2015. "Supporting Python 3: An in-depth guide." Accessed 2018-02-19.
  3. Cannon, Brett. 2015. "Why Python 3 exists." Tall, Snarky Canadian. December 16. Accessed 2018-02-19.
  4. Coghlan, Nick. 2012. "Python 3 Q & A." Nick Coghlan's Python Notes. June 29. Updated 2017-04-22. Accessed 2018-02-19.
  5. van Rossum, Guido. 2018. "What’s New In Python 3.0." Python Docs. Accessed 2018-02-20.

Article Stats

Author-wise Stats for Article Edits

No. of Edits
No. of Chats

Cite As

Devopedia. 2022. "Python 2 vs 3." Version 8, February 15. Accessed 2024-06-25.
Contributed by
2 authors

Last updated on
2022-02-15 12:12:11