O documento discute estratégias para tornar código Python 2 compatível com Python 3, sem torná-lo incompatível com Python 2. Algumas estratégias incluem:
1. Usar módulos como future_builtins e __future__ para lidar com diferenças nos nomes e comportamentos de funções entre as versões.
2. Verificar a versão do Python usando sys.version_info e tratar casos de forma diferente para cada versão.
3. Usar funções como getattr para obter objetos de forma genérica, independente da versão.
(2013-10-02) [PythonBrasil] Compatibilidade entre Python 2 e 3
1. 1
Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 3
2013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini
Brasília – DFBrasília – DF
Centro de ConvençõesCentro de Convenções
Ulysses GuimarãesUlysses Guimarães
Compatibilidade entreCompatibilidade entre
Python 2 e 3Python 2 e 3
Como portar seu código
em Python 2.x
para o Python 3.x
sem torná-lo incompatível
com o Python 2.x?
Com base na história do pacote AudioLazy
2. 2
Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 3
2013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini
Brasília – DFBrasília – DF
Centro de ConvençõesCentro de Convenções
Ulysses GuimarãesUlysses Guimarães
Por quê?Por quê?
●
Versões futuras do PythonVersões futuras do Python
●
Ampliar o público-alvo de seu projetoAmpliar o público-alvo de seu projeto
– AudioLazyAudioLazy
●
https://pypi.python.org/pypi/audiolazy/https://pypi.python.org/pypi/audiolazy/
●
Pressão social e tecnofílicos!Pressão social e tecnofílicos!
– Software para uso científicoSoftware para uso científico
●
NumPyNumPy
●
MatPlotLibMatPlotLib
●
SciPySciPy
– Notícias recentesNotícias recentes
●
Flask!Flask!
TODOS já são compatíveis
com o Python 3.x!
E outros 2800+ pacotes no PyPI...
Python 2.x is the status
quo, Python 3.x is the
present and future of the
language.
www.python.org
3. 3
Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 3
2013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini
Brasília – DFBrasília – DF
Centro de ConvençõesCentro de Convenções
Ulysses GuimarãesUlysses Guimarães
Valores coletados dia 2013-10-02
Alguns númerosAlguns números
Compatibilidade entre Python 2.7 e
outras versões
Compatibilidade entre Python 3 e
outras versões
4. 4
Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 3
2013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini
Brasília – DFBrasília – DF
Centro de ConvençõesCentro de Convenções
Ulysses GuimarãesUlysses Guimarães
Por onde começarPor onde começar
●
Suíte de testesSuíte de testes
●
Conhecimento sobreConhecimento sobre
as diferenças entreas diferenças entre
versõesversões
– Ler, estudarLer, estudar
– Fuçar, brincar,Fuçar, brincar,
remoer, torturar aremoer, torturar a
linguagemlinguagem
●
Outras ferramentas eOutras ferramentas e
pacotespacotes
– Já solucionaram o mesmoJá solucionaram o mesmo
problema? Como?problema? Como?
– Pacotes de auxílio àPacotes de auxílio à
compatibilizaçãocompatibilização
– Dependências funcionamDependências funcionam
em quais versões doem quais versões do
Python?Python?
●
Diminuir restriçõesDiminuir restrições
5. 5
Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 3
2013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini
Brasília – DFBrasília – DF
Centro de ConvençõesCentro de Convenções
Ulysses GuimarãesUlysses Guimarães
Parte 1Parte 1
Tipos de diferençasTipos de diferenças
6. 6
Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 3
2013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini
Brasília – DFBrasília – DF
Centro de ConvençõesCentro de Convenções
Ulysses GuimarãesUlysses Guimarães
Nomes e localizaçõesNomes e localizações
import Tkinter
master = Tkinter.Tk()
master.mainloop()
import Tkinter
master = Tkinter.Tk()
master.mainloop()
import tkinter
master = tkinter.Tk()
master.mainloop()
import tkinter
master = tkinter.Tk()
master.mainloop()
Apenas Python 2Apenas Python 2 Apenas Python 3Apenas Python 3
Traceback (most recent call last):
[...]
ImportError: No module named Tkinter
Traceback (most recent call last):
[...]
ImportError: No module named Tkinter
Rodando no Python 3Rodando no Python 3
Rodando no Python 2Rodando no Python 2
Traceback (most recent call last):
[...]
ImportError: No module named tkinter
Traceback (most recent call last):
[...]
ImportError: No module named tkinter
7. 7
Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 3
2013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini
Brasília – DFBrasília – DF
Centro de ConvençõesCentro de Convenções
Ulysses GuimarãesUlysses Guimarães
Nomes e localizaçõesNomes e localizações
com try...exceptcom try...except
try:
import tkinter
except ImportError:
import Tkinter as tkinter
master = tkinter.Tk()
master.mainloop()
try:
import tkinter
except ImportError:
import Tkinter as tkinter
master = tkinter.Tk()
master.mainloop()
●
Nome únicoNome único
– ““as” no importas” no import
– AtribuiçãoAtribuição
●
Há critérios para uso doHá critérios para uso do
nome?nome?
– PEP8PEP8
– Nome no Python 3Nome no Python 3
●
Versões futurasVersões futuras
– Nome no Python 2Nome no Python 2
●
Atual hábitoAtual hábito
●
Ausente no Python 3Ausente no Python 3
Quais nomes foram “trocados”?
Quais nomes foram “trocados”?
Documentação para
Documentação para
desenvolvedores!
desenvolvedores!
8. 8
Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 3
2013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini
Brasília – DFBrasília – DF
Centro de ConvençõesCentro de Convenções
Ulysses GuimarãesUlysses Guimarães
Módulo future_builtinsMódulo future_builtins
In [1]: import future_builtins
In [2]: dir(future_builtins)
Out[2]:
['__doc__',
'__file__',
'__name__',
'__package__',
'ascii',
'filter',
'hex',
'map',
'oct',
'zip']
In [1]: import future_builtins
In [2]: dir(future_builtins)
Out[2]:
['__doc__',
'__file__',
'__name__',
'__package__',
'ascii',
'filter',
'hex',
'map',
'oct',
'zip']
Fazer zip/map/filter do Python 2 funcionar comoFazer zip/map/filter do Python 2 funcionar como
no Python 3 (módulo existe somente no Python 2)no Python 3 (módulo existe somente no Python 2)
try:
from future_builtins import *
except ImportError:
pass # Python 3
try:
from future_builtins import *
except ImportError:
pass # Python 3
9. 9
Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 3
2013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini
Brasília – DFBrasília – DF
Centro de ConvençõesCentro de Convenções
Ulysses GuimarãesUlysses Guimarães
““Módulo” __future__Módulo” __future__
In [1]: import __future__
In [2]: dir(__future__)
Out[2]:
[ ... ,
'absolute_import',
'all_feature_names',
'division',
'generators',
'nested_scopes',
'print_function',
'unicode_literals',
'with_statement']
In [1]: import __future__
In [2]: dir(__future__)
Out[2]:
[ ... ,
'absolute_import',
'all_feature_names',
'division',
'generators',
'nested_scopes',
'print_function',
'unicode_literals',
'with_statement']
●
Linha inicial de seu códigoLinha inicial de seu código
– Importar antes de outros importsImportar antes de outros imports
●
Existe no Python 2 e 3Existe no Python 2 e 3
10. 10
Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 3
2013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini
Brasília – DFBrasília – DF
Centro de ConvençõesCentro de Convenções
Ulysses GuimarãesUlysses Guimarães
Nomes e localizaçõesNomes e localizações
com verificação préviacom verificação prévia
●
sys.version_infosys.version_info
●
sys.modulessys.modules
import sys
PYTHON2 = sys.version_info.major == 2
if PYTHON2:
builtins = sys.modules["__builtin__"]
else:
import builtins
import sys
PYTHON2 = sys.version_info.major == 2
if PYTHON2:
builtins = sys.modules["__builtin__"]
else:
import builtins
11. 11
Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 3
2013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini
Brasília – DFBrasília – DF
Centro de ConvençõesCentro de Convenções
Ulysses GuimarãesUlysses Guimarães
Módulo sysMódulo sys
In [1]: import sys
In [2]: sys.version_info
Out[2]: sys.version_info(major=3, minor=2,
micro=4, releaselevel='final', serial=0)
In [3]: sys.version_info >= (3, 2)
Out[3]: True
In [4]: sys.version_info >= (3, 3)
Out[4]: False
In [5]: sys.version
Out[5]: '3.2.4 (default, May 8 2013,
20:55:18) n[GCC 4.7.3]'
In [1]: import sys
In [2]: sys.version_info
Out[2]: sys.version_info(major=3, minor=2,
micro=4, releaselevel='final', serial=0)
In [3]: sys.version_info >= (3, 2)
Out[3]: True
In [4]: sys.version_info >= (3, 3)
Out[4]: False
In [5]: sys.version
Out[5]: '3.2.4 (default, May 8 2013,
20:55:18) n[GCC 4.7.3]'
12. 12
Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 3
2013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini
Brasília – DFBrasília – DF
Centro de ConvençõesCentro de Convenções
Ulysses GuimarãesUlysses Guimarães
Nomes e localizaçõesNomes e localizações
com getattrcom getattr
●
Funções são objetosFunções são objetos
●
Análogo ao método “get” de dicionáriosAnálogo ao método “get” de dicionários
import itertools
xzip = getattr(itertools, "izip", zip)
xmap = getattr(itertools, "imap", map)
xfilter = getattr(itertools, "ifilter", filter)
# Usando o builtins visto anteriormente
xrange = getattr(builtins, "xrange", range)
import itertools
xzip = getattr(itertools, "izip", zip)
xmap = getattr(itertools, "imap", map)
xfilter = getattr(itertools, "ifilter", filter)
# Usando o builtins visto anteriormente
xrange = getattr(builtins, "xrange", range)
13. 13
Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 3
2013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini
Brasília – DFBrasília – DF
Centro de ConvençõesCentro de Convenções
Ulysses GuimarãesUlysses Guimarães
Monkeypatch / MockMonkeypatch / Mock
●
Usando getattr e atribuiçõesUsando getattr e atribuições
●
Compatibilizar código de terceiros sem mudá-losCompatibilizar código de terceiros sem mudá-los
●
Nem sempre é possível (tipos básicos)Nem sempre é possível (tipos básicos)
– e.g. Método to_bytes do int (apenas Python 3)e.g. Método to_bytes do int (apenas Python 3)
import operator
operator.div = getattr(operator,
"div",
operator.truediv)
import operator
operator.div = getattr(operator,
"div",
operator.truediv)
In [1]: (317215).to_bytes(5, "big")
Out[1]: b'x00x00x04xd7x1f'
In [1]: (317215).to_bytes(5, "big")
Out[1]: b'x00x00x04xd7x1f'
14. 14
Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 3
2013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini
Brasília – DFBrasília – DF
Centro de ConvençõesCentro de Convenções
Ulysses GuimarãesUlysses Guimarães
Funções e outros objetosFunções e outros objetos
ausentesausentes
●
ReconstruirReconstruir
●
Criar pela primeira vezCriar pela primeira vez
– e.g. itertools.accumulatee.g. itertools.accumulate
●
audiolazy.accumulateaudiolazy.accumulate
from functools import wraps
@wraps(range)
def orange(*args, **kwargs):
return list(range(*args, **kwargs))
from functools import wraps
@wraps(range)
def orange(*args, **kwargs):
return list(range(*args, **kwargs))
15. 15
Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 3
2013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini
Brasília – DFBrasília – DF
Centro de ConvençõesCentro de Convenções
Ulysses GuimarãesUlysses Guimarães
Métodos ausentesMétodos ausentes
●
Iteração sobre dicionáriosIteração sobre dicionários
●
Iterável VS IteradorIterável VS Iterador
– Gotcha!Gotcha!
def iteritems(dictionary):
try:
return getattr(dictionary, "iteritems")()
except AttributeError:
return iter(getattr(dictionary, "items")())
def iteritems(dictionary):
try:
return getattr(dictionary, "iteritems")()
except AttributeError:
return iter(getattr(dictionary, "items")())
16. 16
Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 3
2013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini
Brasília – DFBrasília – DF
Centro de ConvençõesCentro de Convenções
Ulysses GuimarãesUlysses Guimarães
str / intstr / int
no Python 3no Python 3
●
String?String?
– str no Python 3str no Python 3
– (unicode, str) no Python 2(unicode, str) no Python 2
●
builtins.basestringbuiltins.basestring
●
Inteiro?Inteiro?
– int no Python 3int no Python 3
– (long, int) no Python 2(long, int) no Python 2
INT_TYPES = (int, getattr(builtins, "long", None))
if PYTHON2 else (int,)
print(isinstance(something_here, INT_TYPES))
INT_TYPES = (int, getattr(builtins, "long", None))
if PYTHON2 else (int,)
print(isinstance(something_here, INT_TYPES))
Utilização com
Utilização comisinstance
isinstance
17. 17
Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 3
2013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini
Brasília – DFBrasília – DF
Centro de ConvençõesCentro de Convenções
Ulysses GuimarãesUlysses Guimarães
InternalidadesInternalidades
●
Iteradores (e geradores)Iteradores (e geradores)
– Método next no Python 2Método next no Python 2
– Método __next__ no Python 3Método __next__ no Python 3
●
Avaliação “if obj:” segue um método de objAvaliação “if obj:” segue um método de obj
– __nonzero__ no Python 2__nonzero__ no Python 2
– __bool__ no Python 3__bool__ no Python 3
●
Função do método (“unbound”)Função do método (“unbound”)
– Python 2Python 2
●
classe.metodo.im_funcclasse.metodo.im_func
●
objeto.metodo.im_funcobjeto.metodo.im_func
– Python 3Python 3
●
classe.metodoclasse.metodo
●
objeto.metodo.__func__objeto.metodo.__func__
18. 18
Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 3
2013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini
Brasília – DFBrasília – DF
Centro de ConvençõesCentro de Convenções
Ulysses GuimarãesUlysses Guimarães
Parte 2Parte 2
TestesTestes
19. 19
Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 3
2013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini
Brasília – DFBrasília – DF
Centro de ConvençõesCentro de Convenções
Ulysses GuimarãesUlysses Guimarães
TestesTestes
●
AutomatizadosAutomatizados
– py.testpy.test
– nosenose
– unittestunittest
– doctestdoctest
●
Cobertura de códigoCobertura de código
– ConfiabilidadeConfiabilidade
– DependênciasDependências
●
skipskip
●
xfailxfail
●
CompatibilizarCompatibilizar
dependênciadependência
Testes passandoTestes passando
Testes falhandoTestes falhando
20. 20
Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 3
2013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini
Brasília – DFBrasília – DF
Centro de ConvençõesCentro de Convenções
Ulysses GuimarãesUlysses Guimarães
Skip automático comSkip automático com
py.testpy.test
import pytest
def skipper(msg="There's something not supported "
"in this environment"):
def skip(*args, **kwargs):
pytest.skip(msg.format(*args, **kwargs))
return skip
operator.div = getattr(operator, "div",
skipper("There's no "
"operator.div"))
import pytest
def skipper(msg="There's something not supported "
"in this environment"):
def skip(*args, **kwargs):
pytest.skip(msg.format(*args, **kwargs))
return skip
operator.div = getattr(operator, "div",
skipper("There's no "
"operator.div"))
21. 21
Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 3
2013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini
Brasília – DFBrasília – DF
Centro de ConvençõesCentro de Convenções
Ulysses GuimarãesUlysses Guimarães
toxtox
[tox]
envlist = py26,py27
[testenv]
deps=pytest
commands=py.test
[tox]
envlist = py26,py27
[testenv]
deps=pytest
commands=py.test
●
““Standardize testing in Python”Standardize testing in Python”
●
tox.initox.ini
22. 22
Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 3
2013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini
Brasília – DFBrasília – DF
Centro de ConvençõesCentro de Convenções
Ulysses GuimarãesUlysses Guimarães
Parte 3Parte 3
Diferenças importantesDiferenças importantes
!
23. 23
Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 3
2013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini
Brasília – DFBrasília – DF
Centro de ConvençõesCentro de Convenções
Ulysses GuimarãesUlysses Guimarães
MetaclassesMetaclasses
●
Classe cujas instâncias são classesClasse cujas instâncias são classes
●
Sintaxe diferenciada no Python 2 e 3Sintaxe diferenciada no Python 2 e 3
# Python 3
bases = (object,)
MyMeta = type
class A(*bases, metaclass=MyMeta):
pass
# Python 2
class A(*bases):
__metaclass__ = MyMeta
# Python 3
bases = (object,)
MyMeta = type
class A(*bases, metaclass=MyMeta):
pass
# Python 2
class A(*bases):
__metaclass__ = MyMeta
24. 24
Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 3
2013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini
Brasília – DFBrasília – DF
Centro de ConvençõesCentro de Convenções
Ulysses GuimarãesUlysses Guimarães
MetaclassesMetaclasses
●
Solução padrão:Solução padrão:
– Criar uma classeCriar uma classe
vazia usando avazia usando a
metaclasse, e colocá-metaclasse, e colocá-
la junto às basesla junto às bases
●
Problemas:Problemas:
– Construtor da classeConstrutor da classe
pode falharpode falhar
●
Solução alternativaSolução alternativa
– Metaclasse falsaMetaclasse falsa
●
Única base da novaÚnica base da nova
classeclasse
– Construtor daConstrutor da
metaclasse com 2metaclasse com 2
comportamentoscomportamentos
●
Antes da obtenção doAntes da obtenção do
dicionário da classedicionário da classe
●
Depois (realDepois (real
instanciação)instanciação)
– Função audiolazy.metaFunção audiolazy.meta
25. 25
Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 3
2013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini
Brasília – DFBrasília – DF
Centro de ConvençõesCentro de Convenções
Ulysses GuimarãesUlysses Guimarães
>>> class BadMeta(type):
... def __new__(mcls, name, bases, namespace):
... if "bad" not in namespace:
... raise Exception("Oops, not bad enough")
... value = len(name)
... def really_bad(self):
... return self.bad() * value
... namespace["really_bad"] = really_bad
... return super(BadMeta, mcls).__new__(mcls, name, bases,
... namespace)
...
>>> class Bady(meta(object, metaclass=BadMeta)):
... def bad(self):
... return "HUA "
...
>>> class BadGuy(Bady):
... def bad(self):
... return "R"
...
>>> issubclass(BadGuy, Bady)
True
>>> Bady().really_bad() # value = 4
'HUA HUA HUA HUA '
>>> BadGuy().really_bad() # value = 6
'RRRRRR'
>>> class BadMeta(type):
... def __new__(mcls, name, bases, namespace):
... if "bad" not in namespace:
... raise Exception("Oops, not bad enough")
... value = len(name)
... def really_bad(self):
... return self.bad() * value
... namespace["really_bad"] = really_bad
... return super(BadMeta, mcls).__new__(mcls, name, bases,
... namespace)
...
>>> class Bady(meta(object, metaclass=BadMeta)):
... def bad(self):
... return "HUA "
...
>>> class BadGuy(Bady):
... def bad(self):
... return "R"
...
>>> issubclass(BadGuy, Bady)
True
>>> Bady().really_bad() # value = 4
'HUA HUA HUA HUA '
>>> BadGuy().really_bad() # value = 6
'RRRRRR'
26. 26
Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 3
2013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini
Brasília – DFBrasília – DF
Centro de ConvençõesCentro de Convenções
Ulysses GuimarãesUlysses Guimarães
Função “meta”Função “meta”
def meta(*bases, **kwargs):
metaclass = kwargs.get("metaclass", type)
if not bases:
bases = (object,)
class NewMeta(type):
def __new__(mcls, name, mbases, namespace):
if name:
return metaclass.__new__(metaclass, name,
Bases, namespace)
return super(NewMeta, mcls).__new__(mcls, "",
mbases, {})
return NewMeta("", tuple(), {})
def meta(*bases, **kwargs):
metaclass = kwargs.get("metaclass", type)
if not bases:
bases = (object,)
class NewMeta(type):
def __new__(mcls, name, mbases, namespace):
if name:
return metaclass.__new__(metaclass, name,
Bases, namespace)
return super(NewMeta, mcls).__new__(mcls, "",
mbases, {})
return NewMeta("", tuple(), {})
●
Passo 1 – Criar classe com metaclasse fakePasso 1 – Criar classe com metaclasse fake
– Apenas para obter o “namespace”Apenas para obter o “namespace”
●
Passo 2 – Usar a metaclasse fornecidaPasso 2 – Usar a metaclasse fornecida
27. 27
Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 3
2013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini
Brasília – DFBrasília – DF
Centro de ConvençõesCentro de Convenções
Ulysses GuimarãesUlysses Guimarães
PrintPrint
●
Python 2Python 2
– Statement / comandoStatement / comando
– print >>f, “string”print >>f, “string”
– print “a”, “b”print “a”, “b”
– print “string”,print “string”,
●
Python 3Python 3
– FunçãoFunção
– print(“string”, file = f)print(“string”, file = f)
– print(“a”, “b”, sep=“ ”)print(“a”, “b”, sep=“ ”)
– print(“string”, end=“ ”)print(“string”, end=“ ”)
●
Solução (parcial) imediataSolução (parcial) imediata
– from __future__ import print_functionfrom __future__ import print_function
Almost there...Almost there...
28. 28
Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 3
2013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini
Brasília – DFBrasília – DF
Centro de ConvençõesCentro de Convenções
Ulysses GuimarãesUlysses Guimarães
Unicode!!!Unicode!!!
●
Nomes de variável em unicodeNomes de variável em unicode
●
*.py em UTF-8 (Python 3)*.py em UTF-8 (Python 3)
– No Python 2, em uma das 2 primeiras linhas:No Python 2, em uma das 2 primeiras linhas:
# coding: utf-8# coding: utf-8
●
Pensar no unicode (str do Python 3) como um objeto.Pensar no unicode (str do Python 3) como um objeto.
– Encode: codifica o unicode para uma string de bytesEncode: codifica o unicode para uma string de bytes
– Decode: dos bytes, obtém o unicodeDecode: dos bytes, obtém o unicode
●
The Absolute Minimum Every Software DeveloperThe Absolute Minimum Every Software Developer
Absolutely, Positively Must Know About UnicodeAbsolutely, Positively Must Know About Unicode
and Character Sets (No Excuses!)and Character Sets (No Excuses!)
http://www.joelonsoftware.com/articles/Unicode.htmlhttp://www.joelonsoftware.com/articles/Unicode.html
29. 29
Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 3
2013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini
Brasília – DFBrasília – DF
Centro de ConvençõesCentro de Convenções
Ulysses GuimarãesUlysses Guimarães
Unicode!!!Unicode!!!
●
u“texto” (Python 3.3 e 2.x)u“texto” (Python 3.3 e 2.x)
●
from __future__ import unicode_literalsfrom __future__ import unicode_literals
– Funciona no Python 3.2Funciona no Python 3.2
●
Conversão manual (testar tipo)Conversão manual (testar tipo)
●
Provavelmente o aspecto mais difícil durante aProvavelmente o aspecto mais difícil durante a
compatibilizaçãocompatibilização
– os.urandom no simplekv (flask-kvsession)os.urandom no simplekv (flask-kvsession)
30. 30
Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 3
2013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini
Brasília – DFBrasília – DF
Centro de ConvençõesCentro de Convenções
Ulysses GuimarãesUlysses Guimarães
Itertools e functoolsItertools e functools
●
reducereduce
– from functools import reducefrom functools import reduce
●
zip, map, filter (e zip_longest)zip, map, filter (e zip_longest)
– Python 2: ListasPython 2: Listas
– Python 3: Comportamento tardio (lazy), similar aoPython 3: Comportamento tardio (lazy), similar ao
izip, imap, ifilter do itertools do Python 2izip, imap, ifilter do itertools do Python 2
●
ItertoolsItertools
– Não possui mais izip, imap, ifilter, izip_longestNão possui mais izip, imap, ifilter, izip_longest
– Novo accumulateNovo accumulate
31. 31
Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 3
2013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini
Brasília – DFBrasília – DF
Centro de ConvençõesCentro de Convenções
Ulysses GuimarãesUlysses Guimarães
DivisãoDivisão
●
1 / 21 / 2
– 0 no Python 2 (int)0 no Python 2 (int)
– 0.5 no Python 3 (float)0.5 no Python 3 (float)
●
1 // 21 // 2
– 0 no Python 2 (int)0 no Python 2 (int)
– 0 no Python 3 (int)0 no Python 3 (int)
●
Solução imediataSolução imediata
– from __future__ import divisionfrom __future__ import division
32. 32
Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 3
2013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini
Brasília – DFBrasília – DF
Centro de ConvençõesCentro de Convenções
Ulysses GuimarãesUlysses Guimarães
Parte 4Parte 4
Diferenças inusitadasDiferenças inusitadas
33. 33
Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 3
2013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini
Brasília – DFBrasília – DF
Centro de ConvençõesCentro de Convenções
Ulysses GuimarãesUlysses Guimarães
Arredondamento de pontoArredondamento de ponto
flutuanteflutuante
In [1]: round(.5)
Out[1]: 1.0
In [2]: round(-.5)
Out[2]: -1.0
In [1]: round(.5)
Out[1]: 1.0
In [2]: round(-.5)
Out[2]: -1.0
●
Python 2Python 2 ●
Python 3Python 3
●
Solução? Depende do comportamento desejadoSolução? Depende do comportamento desejado
– audiolazy.rintaudiolazy.rint
In [1]: round(.5)
Out[1]: 0
In [2]: round(-.5)
Out[2]: 0
In [1]: round(.5)
Out[1]: 0
In [2]: round(-.5)
Out[2]: 0
34. 34
Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 3
2013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini
Brasília – DFBrasília – DF
Centro de ConvençõesCentro de Convenções
Ulysses GuimarãesUlysses Guimarães
Namespace da classeNamespace da classe
●
Python 2Python 2
– Funciona okFunciona ok
●
Python 3Python 3
– NameError: globalNameError: global
name 'data' is notname 'data' is not
defineddefined
class A(object):
data = [1, 2, 3]
data_powers = [[x ** n for x in data]
for n in range(3)]
class A(object):
data = [1, 2, 3]
data_powers = [[x ** n for x in data]
for n in range(3)]
●
CompatibilizarCompatibilizar
– data_powers = (lambda data: […])(data)data_powers = (lambda data: […])(data)
– Deixar fora da classeDeixar fora da classe
– Colocar no __init__ ou no __new__ da metaclasseColocar no __init__ ou no __new__ da metaclasse
35. 35
Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 3
2013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini
Brasília – DFBrasília – DF
Centro de ConvençõesCentro de Convenções
Ulysses GuimarãesUlysses Guimarães
Parte 4Parte 4
FinalizaçãoFinalização
36. 36
Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 3
2013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini
Brasília – DFBrasília – DF
Centro de ConvençõesCentro de Convenções
Ulysses GuimarãesUlysses Guimarães
Python 2.6 e 2.7Python 2.6 e 2.7
●
Apenas no Python 2.7Apenas no Python 2.7
– Dict comprehensionDict comprehension
●
dict((k, v) for k, v in my_iterable)dict((k, v) for k, v in my_iterable)
– Set comprehensionSet comprehension
●
set(el for el in my_iterable)set(el for el in my_iterable)
– collections.OrderedDictcollections.OrderedDict
●
pip install ordereddictpip install ordereddict
●
Outros features do Python 3.1 (backported)Outros features do Python 3.1 (backported)
http://docs.python.org/dev/whatsnew/2.7.htmlhttp://docs.python.org/dev/whatsnew/2.7.html
Comprehension com {}:
Comprehension com {}:
apenas Python 2.7, 3.1 e
apenas Python 2.7, 3.1 e
mais recentes
mais recentes
37. 37
Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 3
2013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini
Brasília – DFBrasília – DF
Centro de ConvençõesCentro de Convenções
Ulysses GuimarãesUlysses Guimarães
sixsix
●
Pacote de compatibilizaçãoPacote de compatibilização
– Funções para iterar em dicionáriosFunções para iterar em dicionários
– Constantes com tipos para uso com isinstanceConstantes com tipos para uso com isinstance
– callable (Ausente no Python 3 até o 3.1)callable (Ausente no Python 3 até o 3.1)
– Preocupação com Python 2.4 e 2.5Preocupação com Python 2.4 e 2.5
●
Avaliação tardiaAvaliação tardia
– Não importa nada à toaNão importa nada à toa
– Engana análise para auto-completeEngana análise para auto-complete
●
Metaclasse (mantém um nível hierárquico adicional)Metaclasse (mantém um nível hierárquico adicional)
– class A(with_metaclass(Meta, Base)) # Apenas uma baseclass A(with_metaclass(Meta, Base)) # Apenas uma base
– Neste caso, a audiolazy.meta é mais geralNeste caso, a audiolazy.meta é mais geral
Utilizado pelo
Utilizado peloMatPlotLib
MatPlotLib
38. 38
Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 3
2013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini
Brasília – DFBrasília – DF
Centro de ConvençõesCentro de Convenções
Ulysses GuimarãesUlysses Guimarães
ninenine
●
Favorece o Python 3Favorece o Python 3
●
Para código a partir do Python 2.6Para código a partir do Python 2.6
●
Boilerplate sugeridoBoilerplate sugerido
# -*- coding: utf-8 -*-
from __future__ import (absolute_import, division,
print_function,
unicode_literals)
from nine import (IS_PYTHON2, str, basestring,
native_str, chr, integer_types, class_types,
range, range_list, reraise, iterkeys, itervalues,
iteritems, map, zip, filter, input,
implements_iterator, implements_to_string,
implements_repr, nine, nimport)
# -*- coding: utf-8 -*-
from __future__ import (absolute_import, division,
print_function,
unicode_literals)
from nine import (IS_PYTHON2, str, basestring,
native_str, chr, integer_types, class_types,
range, range_list, reraise, iterkeys, itervalues,
iteritems, map, zip, filter, input,
implements_iterator, implements_to_string,
implements_repr, nine, nimport)
39. 39
Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 3
2013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini
Brasília – DFBrasília – DF
Centro de ConvençõesCentro de Convenções
Ulysses GuimarãesUlysses Guimarães
Alternativas à compatibilizaçãoAlternativas à compatibilização
●
Conversão automáticaConversão automática
– Distribute com 2to3 ou 3to2Distribute com 2to3 ou 3to2
●
Conversão manualConversão manual
– Branches para cada versãoBranches para cada versão
●
IncompatibilidadeIncompatibilidade
– Código [parcialmente] restrito a versões específicasCódigo [parcialmente] restrito a versões específicas
●
““Imports” localizados apenas onde necessárioImports” localizados apenas onde necessário
40. 40
Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 3
2013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini
Brasília – DFBrasília – DF
Centro de ConvençõesCentro de Convenções
Ulysses GuimarãesUlysses Guimarães
Obrigado!Obrigado!
>>> from audiolazy import lazy_compat as compat
>>> dir(compat)
['INT_TYPES', 'NEXT_NAME', 'PYTHON2',
'SOME_GEN_TYPES', 'STR_TYPES', '__all__',
'__builtins__', '__cached__', '__doc__', '__file__',
'__name__', '__package__', 'builtins', 'im_func',
'it', 'iteritems', 'itervalues', 'meta', 'orange',
'sys', 'types', 'xfilter', 'xmap', 'xrange', 'xzip',
'xzip_longest']
>>> from audiolazy import lazy_compat as compat
>>> dir(compat)
['INT_TYPES', 'NEXT_NAME', 'PYTHON2',
'SOME_GEN_TYPES', 'STR_TYPES', '__all__',
'__builtins__', '__cached__', '__doc__', '__file__',
'__name__', '__package__', 'builtins', 'im_func',
'it', 'iteritems', 'itervalues', 'meta', 'orange',
'sys', 'types', 'xfilter', 'xmap', 'xrange', 'xzip',
'xzip_longest']
Perguntas?Perguntas?
https://github.com/danilobellini/audiolazyhttps://github.com/danilobellini/audiolazy
@danilobellini@danilobellini
danilo [dot] bellini [at] gmail [dot] comdanilo [dot] bellini [at] gmail [dot] com