# Difference between Python 2 and Python 3 with Examples

In previous lesson, we studied Python’s brief explanation and key importance in version 3. Now we’ll discuss the difference between Python 2 and Python 3.

## Import __future__ module

Python 3 got many new features that are incompatible with Python 2 which can be used in version 2 by importing them using built-in module called `__future__`. For example, see below

``from __future__ import division``

## Integer division

In Python 2, Division of two integers are rounded to nearest integer i.e. 10/3 = 3.

In Python 3, Division gives floating point result which is similar to human calculation i.e. 10/3 = 3.333. To achieve this in version 2 either of two integers should be floating point like 10/3.0 or 10.0/3 and by using `__future__` module.

``````#Python 2.x

>>> print 10/3
3
>>> print 10/3.0, 10.0/3
3.333 3.333

#Python 2.x importing __future__ module

from __future__ import division
>>>print 10/3
3.3333

#Python 3.x

>>> print (10/3)
3.3333
print("thank you")
``````

## Input from Keyboard

Python 2.x has two function namely `raw_input()` and `input()` to take input from user. Keyword `raw_input()` treats everything entered as string and assign to given variable, while `input()` function treats entered number as integer and input entered under quotes (“xyz” or ‘xyz’) treated as string.

``````#Python 2
>>>x=raw_input(‘Given input:’)
Given input: 12
>>>x
‘12’
>>> x=input(‘Given input:’)
Given input:12
>>> x
12
>>> x=input(‘Given input:’)
Given input: ‘12’
>>>x
‘12’``````

In Python 3.x, `raw_input()` function removed and uses `input()` which treats everything entered as string, numbers are explicitly converted in to integers with suffix `int` keyword to

``````#Python 3
>>> x = input('Entered input:')
Entered input :10
>>> x
'10'
>>> x=int(input("Enter"))
Enter:10
>>> x
10
>>> x+10
20``````

## Print Function

Most well know change in Python 3 is `print()` function. In Python 2, `print` function with or without parenthesis is valid i.e. `print()` and `print` to display the output, but in Python 3 parenthesis are mandatory to display output else it will raise a syntax error.

Note: single and double quotes (‘x’ or “x”) used for strings.

``````#Python 2
>>> print ‘Welcome to Externcode.com’
Welcome to Externcode.com
>>> print(“Welcome to Externcode.com”)
Welcome to Externcode.com

#Python 3
>>> print(‘Welcome to Externcode.com’)
Welcome to Externcode.com
>>> print ‘Welcome to Externcode.com’

SyntaxError: Missing parentheses in call to 'print'.
Did you mean print('Welcome to Externcode.com')?``````

## Unicode Support

Python language supports two types of strings Unicode and bytes.

Python 2 stores string as ASCII characters by default. To save string as Unicode we need mark the string explicitly with prefix ‘u’ `(u’string’)` whereas bytes used to store arbitrary binary data.

For version 2.x both Unicode and byte are basically same type i.e. string can be added.

``````#Python 2
>>> print type('string')
<type 'str'>
>>> print type(u'string')
<type 'unicode'>
>>>print type(b'string')
<type 'str'>
>>> print 'you can add string' + b' the byte'
you can add string the byte``````

In Python 3 strings are Unicode by default and has separate type class for byte. If you want to make sure Python 3 code is compatible with Python 2 mark it Unicode strings with a “u”.

``````#Python 3
>>>type('string')
<class'str'>
>>> type(u'externcode.com')
<class'str'>
>>> type(b'externcode.com')
<class'bytes'>
>>> print('you cannot add string' + b' bytes ')

Traceback (most recent call last):
File "<pyshell#8>", line 1,in <module>
print('note that we cannot add a string' + b'bytes for data')
TypeError:can only concatenate str (not "bytes") to str
``````

## Xrange() and range()

Python use generators which are effective at utilization of memory. In Python 2, `xrange()` is a generator, and `range()` give a list of items.

``````#Python 2
>>> for x in xrange(1, 5): print(x)
1 2 3 4
>>> for x in range(1, 5): print(x)
1 2 3 4``````

In Python 3, the `range()` function is deprecated, and `xrange()` renamed as `range()`. Any operator which was returning a list of items in 2.x is replaced with a generator object in version 3.

``````#Python 3
>>> range(5)
range(0, 5)
>>> for i in range(5): print(i)
0
1
2
3
4
>>> xrange()

Traceback (most recent call last):
File "<pyshell#15>", line 1,in <module>
xrange()
NameError:name 'xrange' is not defined
``````

## Raising an Exceptions

While raising an exception in Python 2, exception arguments can be enclosed in parentheses and even works without parenthesis.

``````#Python 2
>>> raise IOError, "error"

Traceback (most recent call last):
File "<pyshell#0>", line 1, in <module>
raise IOError, " error"
OSError: error
>>> raise IOError("error")

Traceback (most recent call last):
File "<pyshell#0>", line 1, in <module>
raise IOError(" error")
OSError: error``````

But in Python 3, raising an exception use of parenthesis are mandatory.

``````#Python 3
>>> raise IOError("error")

Traceback (most recent call last):
File "<pyshell#0>", line 1, in <module>
raise IOError("error")
OSError: file error
>>> raise IOError," error" #without ()

SyntaxError: invalid syntax
``````

## Exception Handling

A small in version 3 replacing comma with “as”.

`````` #Python 2
try:
Error_Occured
except NameError, error:
print error, '-- our error message'

#OUTPUT
name 'Error_Occured' is not defined -- our error message

#Python 3
try:
Error_Occured
except NameError as error:
print (error, '-- our error message')

#OUTPUT
name 'Error_Occured' is not defined -- our error message
``````