<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Moving from Python 2 to Python 3
Python 2 has a limited lifetime, and by 2020, there will no longer be any active development on Python 2.
http
Step1:  A (non-exhaustive) list of differences between Python 2 and Python 3
print is now a function, no longer a keyword
exec is now a function, no longer a keyword
division, /, no longer truncates! (no more 2/3 == 0)
all strings are unicode (this is... controversial)
the functions range(), zip(), map(), filter(), dict.keys(), dict.items(), dict.values(), all return an iterator instead of a list
exceptions are handled using a slightly different syntax
strict comparisons, so 'a' &lt; 1 will fail with an error
from the standard library, urllib is reorganized
For a more complete list, see 
http
Step2:  New string formatting
The old string formatting (with %) is depricated in favor of str.format().  A good comparison of the two can be found here
Step3:  Writing code for both Python 2 and Python 3
Ever wonder what those from __future__ import foo statements were doing?
http
<ASSISTANT_TASK:>
Python Code:
import sys
print(sys.version)
Explanation: Moving from Python 2 to Python 3
Python 2 has a limited lifetime, and by 2020, there will no longer be any active development on Python 2.
http://legacy.python.org/dev/peps/pep-0373/
Why?  Apparently it was easier to make a shiny new python by breaking backwards compatibility.  The good news is it's relatively painless to switch small projects over to Python 3, and most major Python packages already support Python 3 (including most of the scientific stack: numpy, scipy, pandas, astropy).
End of explanation
# python2 has list comprehensions
[x ** 2 for x in range(5)]
# python3 has dict comprehensions!
{str(x): x ** 2 for x in range(5)}
# and set comprehensions
{x ** 2 for x in range(5)}
# magic dictionary concatenation
some_kwargs = {'do': 'this', 
               'not': 'that'}
other_kwargs = {'use': 'something', 
                'when': 'sometime'}
{**some_kwargs, **other_kwargs}
# unpacking magic
a, *stuff, b = range(5)
print(a)
print(stuff)
print(b)
# native support for unicode
s = 'Το Ζεν του Πύθωνα'
print(s)
# unicode variable names!
import numpy as np
π = np.pi
np.cos(2 * π)
# infix matrix multiplication
A = np.random.choice(list(range(-9, 10)), size=(3, 3))
B = np.random.choice(list(range(-9, 10)), size=(3, 3))
print("A = \n", A)
print("B = \n", B)
print("A B = \n", A @ B)
print("A B = \n", np.dot(A, B))
Explanation: A (non-exhaustive) list of differences between Python 2 and Python 3
print is now a function, no longer a keyword
exec is now a function, no longer a keyword
division, /, no longer truncates! (no more 2/3 == 0)
all strings are unicode (this is... controversial)
the functions range(), zip(), map(), filter(), dict.keys(), dict.items(), dict.values(), all return an iterator instead of a list
exceptions are handled using a slightly different syntax
strict comparisons, so 'a' &lt; 1 will fail with an error
from the standard library, urllib is reorganized
For a more complete list, see 
http://ptgmedia.pearsoncmg.com/imprint_downloads/informit/promotions/python/python2python3.pdf
Cool things in Python 3
Some of these have been back-ported to Python 2.7
End of explanation
s = 'asdf'
b = s.encode('utf-8')
b
b.decode('utf-8')
# this will be problematic if other encodings are used...
s = 'asdf'
b = s.encode('utf-32')
b
b.decode('utf-8')
Explanation: New string formatting
The old string formatting (with %) is depricated in favor of str.format().  A good comparison of the two can be found here: 
https://pyformat.info/
Unicode
Dealing with unicode can be a pain when *nix doesn't give or expect unicode.  Sometimes importing data in python3 will give you strings with a weird b in front.  These are bytestrings, and they can usually be converted to unicode strings with bytestring.decode('utf-8').
End of explanation
# shouldn't change anything in python3
from __future__ import print_function, division
print('non-truncated division in a print function: 2/3 =', 2/3)
Explanation: Writing code for both Python 2 and Python 3
Ever wonder what those from __future__ import foo statements were doing?
http://python-future.org/quickstart.html
Using the future package, you can write code that works for either Python 2 or Python 3.  You'll still have to avoid using some Python 3 specific syntax.
End of explanation
<END_TASK>