import future # pip install future
import builtins # pip install future
import past # pip install future
import six # pip install six
print(six.text_type("a"))
print(type(six.text_type("a")))
a <class 'str'>
from __future__ import (unicode_literals)
print("a")
print(type("a"))
a <class 'str'>
from past.builtins import (str as oldstr)
texto = oldstr(u'孔子'.encode('utf-8'))
print(texto)
print(type(texto))
åå <class 'past.types.oldstr.oldstr'>
# Python 2 and 3:
from __future__ import print_function # (at top of module)
print('BÁSICO:')
print('Hello Guido')
print('CON NUEVOS PARÁMETROS:')
print('Hello', 'Guido', sep=" | ", end="!")
BÁSICO: Hello Guido CON NUEVOS PARÁMETROS: Hello | Guido!
# Python 2 only:
raise ValueError, "dodgy value"
# Python 2 and 3:
raise ValueError("dodgy value")
# Python 2 only:
try:
...
except ValueError, e:
...
# Python 2 and 3:
try:
...
except ValueError as e:
...
from abc import ABCMeta
# Python 2 only:
class MyABC:
__metaclass__ = ABCMeta
pass
from abc import ABC, ABCMeta
class MyABC(ABC):
pass
class MyABC2(metaclass=ABCMeta):
pass
# Python 2 only:
name = raw_input('What is your name? ')
assert isinstance(name, str) # native str
# Python 2 and 3:
from builtins import input
name = input('What is your name? ')
assert isinstance(name, str) # native str on Py2 and Py3
# Python 2 only:
input("Type something safe please: ")
# Python 2 and 3
from builtins import input
eval(input("Type something safe please: "))
# Python 2 only:
import urllib2
url = "http://www.google.com"
html = urllib2.urlopen(url)
# Python 3:
from urllib.request import urlopen
url = "http://www.google.com"
html = urlopen(url)
Supongamos que tenemos un proyecto tal que:
mypython2package/
__init__.py
main.py
main2.py
# Python 2
from . import main2
# Python 2 and 3. GOOD WAY!
from __future__ import absolute_import
# Python 2 and 3:
from mypython2package import main2
# Python 2 only:
assert 2 / 3 == 0
# Python 2 and 3:
assert 2 // 3 == 0
# Python 3 only:
assert 3 / 2 == 1.5
# Python 2 and 3:
from __future__ import division
assert 3 / 2 == 1.5
En Python 2, str
es una secuencia de bytes. unicode
es una representación de un texto
En Python 3, unicode
== str
y str
de Python 2 ahora es bytes
Error típico de Python 2:
SyntaxError: Non-ASCII character '\xc3' in file unicode_error.py on line 1, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details
# Python 2 only
s1 = 'きたないのよりきれいな方がいい\n'
s2 = u'きたないのよりきれいな方がいい\n'
s3 = b'きたないのよりきれいな方がいい\n'
assert s1 is not s2
assert s1 is s3
# Python 2 and 3
from __future__ import unicode_literals # at top of module
s4 = 'きたないのよりきれいな方がいい\n'
s5 = u'きたないのよりきれいな方がいい\n'
assert s4 is s5
# Python 2 only
s6 = 'A byte-string'
# Python 2 and 3
s6 = b'A byte-string'
assert s6 is not s7
# Python 2 and 3: alternative 1
from builtins import str
templates = u"blog/blog_post_detail_%s.html" % str("slug")
print(templates)
blog/blog_post_detail_slug.html
templates = b"blog/blog_post_detail_{}.html".format(b"slug")
--------------------------------------------------------------------------- AttributeError Traceback (most recent call last) <ipython-input-29-508c421c5757> in <module>() ----> 1 templates = b"blog/blog_post_detail_{}.html".format(b"slug") AttributeError: 'bytes' object has no attribute 'format'
print(b"blog/blog_post_detail_%s.html" % b"slug")
import base64
# MAL!!!!
authenticationHeader = {
"Authorization": "Basic {}".format(base64.b64encode(bytes("user:pass", "utf-8")))
}
# BIEN!!!!
authenticationHeader = {
"Authorization": "Basic {}".format(str(base64.b64encode(bytes("user:pass", "utf-8")), "utf-8"))
}
# r = requests.get(url, headers=authenticationHeader)
print("CADENA CODIFICADA")
print(base64.b64encode(bytes("user:pass", "utf-8")), end="\n\n")
print("CADENA FORMATEADA MAL 1")
print("Basic {}".format(base64.b64encode(bytes("user:pass", "utf-8"))), end="\n\n")
print("CADENA FORMATEADA MAL 2")
print("Basic %s" % (base64.b64encode(bytes("user:pass", "utf-8"))), end="\n\n")
print("FORMAS CORRECTAS 1")
print("Basic {}".format(str(base64.b64encode(b"user:pass"), "utf-8")), end="\n\n")
print("Basic {}".format(str(base64.b64encode(bytes("user:pass", "utf-8")), "utf-8")), end="\n\n")
CADENA CODIFICADA b'dXNlcjpwYXNz' CADENA FORMATEADA MAL 1 Basic b'dXNlcjpwYXNz' CADENA FORMATEADA MAL 2 Basic b'dXNlcjpwYXNz' FORMAS CORRECTAS 1 Basic dXNlcjpwYXNz Basic dXNlcjpwYXNz
# Python 2 only:
for (key, value) in heights.iteritems():
print(value)
# Python 2 and 3: option 1
for (key, value) in heights.items(): # inefficient on Py2
print(key, value, sep=": ")
# Python 2 and 3: option 2
from future.utils import viewitems
for (key, value) in viewitems(heights):
print(key, value, sep=": ")
# Python 2 and 3: option 3
from future.utils import iteritems # or from six import iteritems
for (key, value) in iteritems(heights):
print(key, value, sep=": ")
# Python 2
dict_1 = {'a': "Hartu", 'b': "arbasoen"}
dict_2 = {'c': "ohitura", 'd': "zaharrak"}
def merge_two_dicts(x, y):
z = x
z.update(y)
return z
print(merge_two_dicts(dict_1, dict_2))
# Python 3
dict_1 = {'a': "Hartu", 'b': "arbasoen"}
dict_2 = {'c': "ohitura", 'd': "zaharrak"}
print({**dict_1, **dict_2}, end="\n\n")
print(*["\U0001F60D" for i in range(500)], sep=" ")
{'a': 'Hartu', 'b': 'arbasoen', 'c': 'ohitura', 'd': 'zaharrak'} 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍 😍
# Python 2 range:
type(range(5)) # -> <type 'list'>
print(range(5)) # -> [0, 1, 2, 3, 4]
# Python 3 range:
type(range(5)) # -> <class 'range'>
print(range(5)) # -> range(0, 5)
f = lambda x: x*2
lista = [1,2,3]
# Python 2 range:
type(map(f,lista)) # -> <type 'list'>
print(map(f,lista)) # -> [2, 4, 6]
# Python 3 range:
type(map(f,lista)) # -> map
print(map(f,lista)) # -> <map object at 0x7fe89a56d518>
Lo mismo para zip, izip, filter, ifilter....
from past.builtins import reduce
assert reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) == 1+2+3+4+5
assert reduce(lambda x, y: x+y, [(1, 2), (3, 4), (5, 6)]) == (1, 2, 3, 4, 5, 6)
Show all files with python3 errors
apt-get install python3-future
futurize --stage1 mypython2package/*.py
futurize --stage2 mypython2package/*.py
PEP 380 adds the yield from expression, allowing a generator to delegate part of its operations to another generator. This allows a section of code containing yield to be factored out and placed in another generator. Additionally, the subgenerator is allowed to return with a value, and the value is made available to the delegating generator.
def g(x):
yield from range(x, 0, -1)
yield from range(x)
list(g(5))
[5, 4, 3, 2, 1, 0, 1, 2, 3, 4]
More info in python.org
def say_hello(name: str) -> str:
return 'Hello ' + name
say_hello(1)
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-35-1211d3f71547> in <module>() 2 return 'Hello ' + name 3 ----> 4 say_hello(1) <ipython-input-35-1211d3f71547> in say_hello(name) 1 def say_hello(name: str) -> str: ----> 2 return 'Hello ' + name 3 4 say_hello(1) TypeError: must be str, not int
say_hello("Python 3")
'Hello Python 3'
Future: is an object that is supposed to have a result in the future
Task: is a subclass of Future that wraps a coroutine
Coroutines: a generator that return tasks
# Python 3.4 coroutine example
import asyncio
@asyncio.coroutine
def my_coro():
yield from func()
import asyncio
# Python 3.5 coroutine example
async def my_coro():
await func()
#asyncio_0_basic_01.py
import asyncio
import random
"""
@asyncio.coroutine
def compute(x, y):
print("Compute %s + %s ..." % (x, y))
yield from asyncio.sleep(random.randint(1,20))
return x + y
"""
async def compute(x, y):
print("Compute %s + %s ..." % (x, y))
await asyncio.sleep(random.randint(1,20))
return x + y
async def print_sum(x, y):
result = await compute(x, y)
print("%s + %s = %s" % (x, y, result))
loop = asyncio.get_event_loop()
coroutines = [print_sum(i, i+1) for i in range(10)]
loop.run_until_complete(asyncio.wait(coroutines)) # yield from...
Compute 4 + 5 ... Compute 2 + 3 ... Compute 5 + 6 ... Compute 1 + 2 ... Compute 6 + 7 ... Compute 0 + 1 ... Compute 7 + 8 ... Compute 8 + 9 ... Compute 3 + 4 ... Compute 9 + 10 ... 9 + 10 = 19 6 + 7 = 13 7 + 8 = 15 3 + 4 = 7 2 + 3 = 5 1 + 2 = 3 4 + 5 = 9 0 + 1 = 1 5 + 6 = 11 8 + 9 = 17
import random
import asyncio
async def say_boo():
i = 0
while i < 5:
print('...boo {0}'.format(i))
i += 1
await asyncio.sleep(random.randint(0, 5))
async def say_baa():
i = 0
while i < 5:
print('...baa {0}'.format(i))
i += 1
await asyncio.sleep(random.randint(0, 2))
loop = asyncio.get_event_loop()
corrutine_boo = say_boo()
print(corrutine_boo)
asyncio.ensure_future(corrutine_boo)
asyncio.ensure_future(say_baa())
loop.run_forever()
<coroutine object say_boo at 0x7fc680eb3f68>
...boo 0
...baa 0
...boo 1
...boo 4
...baa 1
...baa 2
...baa 3
...baa 4
...boo 2
...boo 3
...boo 4
import asyncio
from concurrent.futures import ProcessPoolExecutor
def say_boo():
i = 0
while i < 5:
print('...boo {0}'.format(i))
i += 1
def say_baa():
i = 0
while i < 5:
print('...baa {0}'.format(i))
i += 1
executor = ProcessPoolExecutor(2)
loop = asyncio.get_event_loop()
future = loop.run_in_executor(executor, say_boo)
print(future)
boo = asyncio.ensure_future(future)
baa = asyncio.ensure_future(loop.run_in_executor(executor, say_baa))
<Future pending cb=[_chain_future.<locals>._call_check_cancel() at /usr/lib/python3.6/asyncio/futures.py:408]>
...boo 0
...baa 0
...baa 1
...baa 2
...baa 3
...baa 4
...boo 1
...boo 2
...boo 3
...boo 4
#asyncio_0_basic_03.py
import asyncio
import concurrent.futures
from time import sleep
import random
loop = asyncio.get_event_loop()
def say_boo(i):
sleep(random.randint(1, 5))
return '...boo {0}'.format(i)
async def thread_results():
with concurrent.futures.ThreadPoolExecutor(max_workers=90) as executor:
futures = [loop.run_in_executor(executor, say_boo, value) for value in range(10)]
for result in await asyncio.gather(*futures):
print("Result", end=": ")
print(result)
loop.run_until_complete(thread_results())
Result: ...boo 0 Result: ...boo 1 Result: ...boo 2 Result: ...boo 3 Result: ...boo 4 Result: ...boo 5 Result: ...boo 6 Result: ...boo 7 Result: ...boo 8 Result: ...boo 9
https://github.com/avara1986/python2to3
@a_vara_n
Python Whats new:
https://docs.python.org/3/whatsnew/3.5.html
Writing Python 2-3 compatible code Cheat Sheet:
http://python-future.org/compatible_idioms.html