(2013-10-02) [PythonBrasil] Compatibilidade entre Python 2 e 3

40
1 Compatibilidade entre Python 2 e 3 Compatibilidade entre Python 2 e 3 2013-10-02 – Danilo J. S. Bellini – @danilobellini 2013-10-02 – Danilo J. S. Bellini – @danilobellini Brasília – DF Brasília – DF Centro de Convenções Centro de Convenções Ulysses Guimarães Ulysses Guimarães Compatibilidade entre Compatibilidade entre Python 2 e 3 Python 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

description

Apresentação realizada durante a PythonBrasil[9]. Segue abaixo a descrição da palestra: Mudanças na especificação da linguagem fizeram o Python 3 incompatível com parte do código escrito para o Python 2. Algumas dessas incompatibilidades podem ser facilmente resolvidas através de traduções, sejam elas automáticas ou não. Porém, muitas dessas traduções trazem consigo uma incompatibilidade com a versão de origem do código (o Python 2, neste caso), o que nem sempre é desejável. É possível manter um único código compatível com o ambos o Python 2 e 3? Esta atividade se propõe a responder essa pergunta, e enfatizará os problemas e soluções que levaram à elaboração do módulo lazy_compat da AudioLazy (e.g. metaclasses, arredondamento de ponto flutuante).

Transcript of (2013-10-02) [PythonBrasil] Compatibilidade entre Python 2 e 3

Page 1: (2013-10-02) [PythonBrasil] Compatibilidade entre Python 2 e 3

1

Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 32013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini

Brasília – DFBrasília – DFCentro de Convenções Centro de Convenções

Ulysses GuimarãesUlysses Guimarães

Compatibilidade entreCompatibilidade entrePython 2 e 3Python 2 e 3

Como portar seu códigoem Python 2.x

para o Python 3.xsem torná-lo incompatível

com o Python 2.x?

Com base na história do pacote AudioLazy

Page 2: (2013-10-02) [PythonBrasil] Compatibilidade entre Python 2 e 3

2

Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 32013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini

Brasília – DFBrasília – DFCentro de Convenções Centro 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íveiscom 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

Page 3: (2013-10-02) [PythonBrasil] Compatibilidade entre Python 2 e 3

3

Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 32013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini

Brasília – DFBrasília – DFCentro de Convenções Centro de Convenções

Ulysses GuimarãesUlysses Guimarães

Valores coletados dia 2013-10-02Alguns númerosAlguns números

Compatibilidade entre Python 2.7 e outras versões

Compatibilidade entre Python 3 e outras versões

Page 4: (2013-10-02) [PythonBrasil] Compatibilidade entre Python 2 e 3

4

Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 32013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini

Brasília – DFBrasília – DFCentro de Convenções Centro de Convenções

Ulysses GuimarãesUlysses Guimarães

Por onde começarPor onde começar

● Suíte de testesSuíte de testes● Conhecimento sobre Conhecimento sobre

as diferenças entre as diferenças entre versõesversões– Ler, estudarLer, estudar

– Fuçar, brincar, Fuçar, brincar, remoer, torturar a remoer, torturar a linguagemlinguagem

● Outras ferramentas e Outras ferramentas e pacotespacotes– Já solucionaram o mesmo Já solucionaram o mesmo

problema? Como?problema? Como?

– Pacotes de auxílio à Pacotes de auxílio à compatibilizaçãocompatibilização

– Dependências funcionam Dependências funcionam em quais versões do em quais versões do Python?Python?

● Diminuir restriçõesDiminuir restrições

Page 5: (2013-10-02) [PythonBrasil] Compatibilidade entre Python 2 e 3

5

Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 32013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini

Brasília – DFBrasília – DFCentro de Convenções Centro de Convenções

Ulysses GuimarãesUlysses Guimarães

Parte 1Parte 1Tipos de diferençasTipos de diferenças

Page 6: (2013-10-02) [PythonBrasil] Compatibilidade entre Python 2 e 3

6

Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 32013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini

Brasília – DFBrasília – DFCentro de Convenções Centro 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

Page 7: (2013-10-02) [PythonBrasil] Compatibilidade entre Python 2 e 3

7

Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 32013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini

Brasília – DFBrasília – DFCentro de Convenções Centro de Convenções

Ulysses GuimarãesUlysses Guimarães

Nomes e localizaçõesNomes e localizaçõescom try...exceptcom try...except

try: import tkinterexcept ImportError: import Tkinter as tkinter

master = tkinter.Tk()master.mainloop()

try: import tkinterexcept 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 do Há 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!

Page 8: (2013-10-02) [PythonBrasil] Compatibilidade entre Python 2 e 3

8

Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 32013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini

Brasília – DFBrasília – DFCentro de Convenções Centro de Convenções

Ulysses GuimarãesUlysses Guimarães

Módulo future_builtinsMódulo future_builtins

In [1]: import future_builtinsIn [2]: dir(future_builtins)Out[2]: ['__doc__', '__file__', '__name__', '__package__', 'ascii', 'filter', 'hex', 'map', 'oct', 'zip']

In [1]: import future_builtinsIn [2]: dir(future_builtins)Out[2]: ['__doc__', '__file__', '__name__', '__package__', 'ascii', 'filter', 'hex', 'map', 'oct', 'zip']

Fazer zip/map/filter do Python 2 funcionar como Fazer 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

Page 9: (2013-10-02) [PythonBrasil] Compatibilidade entre Python 2 e 3

9

Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 32013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini

Brasília – DFBrasília – DFCentro de Convenções Centro 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

Page 10: (2013-10-02) [PythonBrasil] Compatibilidade entre Python 2 e 3

10

Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 32013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini

Brasília – DFBrasília – DFCentro de Convenções Centro de Convenções

Ulysses GuimarãesUlysses Guimarães

Nomes e localizaçõesNomes e localizaçõescom verificação préviacom verificação prévia

● sys.version_infosys.version_info

● sys.modulessys.modules

import sys

PYTHON2 = sys.version_info.major == 2if PYTHON2: builtins = sys.modules["__builtin__"]else: import builtins

import sys

PYTHON2 = sys.version_info.major == 2if PYTHON2: builtins = sys.modules["__builtin__"]else: import builtins

Page 11: (2013-10-02) [PythonBrasil] Compatibilidade entre Python 2 e 3

11

Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 32013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini

Brasília – DFBrasília – DFCentro de Convenções Centro de Convenções

Ulysses GuimarãesUlysses Guimarães

Módulo sysMódulo sysIn [1]: import sys

In [2]: sys.version_infoOut[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.versionOut[5]: '3.2.4 (default, May 8 2013, 20:55:18) \n[GCC 4.7.3]'

In [1]: import sys

In [2]: sys.version_infoOut[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.versionOut[5]: '3.2.4 (default, May 8 2013, 20:55:18) \n[GCC 4.7.3]'

Page 12: (2013-10-02) [PythonBrasil] Compatibilidade entre Python 2 e 3

12

Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 32013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini

Brasília – DFBrasília – DFCentro de Convenções Centro de Convenções

Ulysses GuimarãesUlysses Guimarães

Nomes e localizaçõesNomes e localizaçõescom 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 anteriormentexrange = 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 anteriormentexrange = getattr(builtins, "xrange", range)

Page 13: (2013-10-02) [PythonBrasil] Compatibilidade entre Python 2 e 3

13

Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 32013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini

Brasília – DFBrasília – DFCentro de Convenções Centro 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 operatoroperator.div = getattr(operator, "div", operator.truediv)

import operatoroperator.div = getattr(operator, "div", operator.truediv)

In [1]: (317215).to_bytes(5, "big")Out[1]: b'\x00\x00\x04\xd7\x1f'In [1]: (317215).to_bytes(5, "big")Out[1]: b'\x00\x00\x04\xd7\x1f'

Page 14: (2013-10-02) [PythonBrasil] Compatibilidade entre Python 2 e 3

14

Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 32013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini

Brasília – DFBrasília – DFCentro de Convenções Centro de Convenções

Ulysses GuimarãesUlysses Guimarães

Funções e outros objetos Funçõ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))

Page 15: (2013-10-02) [PythonBrasil] Compatibilidade entre Python 2 e 3

15

Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 32013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini

Brasília – DFBrasília – DFCentro de Convenções Centro 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")())

Page 16: (2013-10-02) [PythonBrasil] Compatibilidade entre Python 2 e 3

16

Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 32013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini

Brasília – DFBrasília – DFCentro de Convenções Centro de Convenções

Ulysses GuimarãesUlysses Guimarães

str / intstr / intno 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 comisinstanceisinstance

Page 17: (2013-10-02) [PythonBrasil] Compatibilidade entre Python 2 e 3

17

Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 32013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini

Brasília – DFBrasília – DFCentro de Convenções Centro 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__

Page 18: (2013-10-02) [PythonBrasil] Compatibilidade entre Python 2 e 3

18

Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 32013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini

Brasília – DFBrasília – DFCentro de Convenções Centro de Convenções

Ulysses GuimarãesUlysses Guimarães

Parte 2Parte 2TestesTestes

Page 19: (2013-10-02) [PythonBrasil] Compatibilidade entre Python 2 e 3

19

Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 32013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini

Brasília – DFBrasília – DFCentro de Convenções Centro 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● Compatibilizar Compatibilizar

dependênciadependência

Testes passandoTestes passando

Testes falhandoTestes falhando

Page 20: (2013-10-02) [PythonBrasil] Compatibilidade entre Python 2 e 3

20

Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 32013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini

Brasília – DFBrasília – DFCentro de Convenções Centro de Convenções

Ulysses GuimarãesUlysses Guimarães

Skip automático comSkip automático compy.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"))

Page 21: (2013-10-02) [PythonBrasil] Compatibilidade entre Python 2 e 3

21

Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 32013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini

Brasília – DFBrasília – DFCentro de Convenções Centro de Convenções

Ulysses GuimarãesUlysses Guimarães

toxtox

[tox]envlist = py26,py27

[testenv]deps=pytestcommands=py.test

[tox]envlist = py26,py27

[testenv]deps=pytestcommands=py.test

● ““Standardize testing in Python”Standardize testing in Python”● tox.initox.ini

Page 22: (2013-10-02) [PythonBrasil] Compatibilidade entre Python 2 e 3

22

Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 32013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini

Brasília – DFBrasília – DFCentro de Convenções Centro de Convenções

Ulysses GuimarãesUlysses Guimarães

Parte 3Parte 3Diferenças importantesDiferenças importantes

!

Page 23: (2013-10-02) [PythonBrasil] Compatibilidade entre Python 2 e 3

23

Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 32013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini

Brasília – DFBrasília – DFCentro de Convenções Centro 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 3bases = (object,)MyMeta = typeclass A(*bases, metaclass=MyMeta): pass

# Python 2class A(*bases): __metaclass__ = MyMeta

# Python 3bases = (object,)MyMeta = typeclass A(*bases, metaclass=MyMeta): pass

# Python 2class A(*bases): __metaclass__ = MyMeta

Page 24: (2013-10-02) [PythonBrasil] Compatibilidade entre Python 2 e 3

24

Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 32013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini

Brasília – DFBrasília – DFCentro de Convenções Centro de Convenções

Ulysses GuimarãesUlysses Guimarães

MetaclassesMetaclasses

● Solução padrão:Solução padrão:– Criar uma classe Criar uma classe

vazia usando a vazia usando a metaclasse, e colocá-metaclasse, e colocá-la junto às basesla junto às bases

● Problemas:Problemas:– Construtor da classe Construtor da classe

pode falharpode falhar

● Solução alternativaSolução alternativa– Metaclasse falsaMetaclasse falsa

● Única base da nova Única base da nova classeclasse

– Construtor da Construtor da metaclasse com 2 metaclasse com 2 comportamentoscomportamentos

● Antes da obtenção do Antes da obtenção do dicionário da classedicionário da classe

● Depois (real Depois (real instanciação)instanciação)

– Função audiolazy.metaFunção audiolazy.meta

Page 25: (2013-10-02) [PythonBrasil] Compatibilidade entre Python 2 e 3

25

Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 32013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini

Brasília – DFBrasília – DFCentro de Convenções Centro 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'

Page 26: (2013-10-02) [PythonBrasil] Compatibilidade entre Python 2 e 3

26

Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 32013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini

Brasília – DFBrasília – DFCentro de Convenções Centro 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

Page 27: (2013-10-02) [PythonBrasil] Compatibilidade entre Python 2 e 3

27

Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 32013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini

Brasília – DFBrasília – DFCentro de Convenções Centro 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...

Page 28: (2013-10-02) [PythonBrasil] Compatibilidade entre Python 2 e 3

28

Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 32013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini

Brasília – DFBrasília – DFCentro de Convenções Centro 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 Developer The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode Absolutely, 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

Page 29: (2013-10-02) [PythonBrasil] Compatibilidade entre Python 2 e 3

29

Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 32013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini

Brasília – DFBrasília – DFCentro de Convenções Centro 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 a Provavelmente o aspecto mais difícil durante a compatibilizaçãocompatibilização– os.urandom no simplekv (flask-kvsession)os.urandom no simplekv (flask-kvsession)

Page 30: (2013-10-02) [PythonBrasil] Compatibilidade entre Python 2 e 3

30

Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 32013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini

Brasília – DFBrasília – DFCentro de Convenções Centro 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 ao Python 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

Page 31: (2013-10-02) [PythonBrasil] Compatibilidade entre Python 2 e 3

31

Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 32013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini

Brasília – DFBrasília – DFCentro de Convenções Centro 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

Page 32: (2013-10-02) [PythonBrasil] Compatibilidade entre Python 2 e 3

32

Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 32013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini

Brasília – DFBrasília – DFCentro de Convenções Centro de Convenções

Ulysses GuimarãesUlysses Guimarães

Parte 4Parte 4Diferenças inusitadasDiferenças inusitadas

Page 33: (2013-10-02) [PythonBrasil] Compatibilidade entre Python 2 e 3

33

Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 32013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini

Brasília – DFBrasília – DFCentro de Convenções Centro de Convenções

Ulysses GuimarãesUlysses Guimarães

Arredondamento de ponto Arredondamento 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

Page 34: (2013-10-02) [PythonBrasil] Compatibilidade entre Python 2 e 3

34

Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 32013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini

Brasília – DFBrasília – DFCentro de Convenções Centro de Convenções

Ulysses GuimarãesUlysses Guimarães

Namespace da classeNamespace da classe

● Python 2Python 2– Funciona okFunciona ok

● Python 3Python 3– NameError: global NameError: global

name 'data' is not name '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

Page 35: (2013-10-02) [PythonBrasil] Compatibilidade entre Python 2 e 3

35

Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 32013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini

Brasília – DFBrasília – DFCentro de Convenções Centro de Convenções

Ulysses GuimarãesUlysses Guimarães

Parte 4Parte 4FinalizaçãoFinalização

Page 36: (2013-10-02) [PythonBrasil] Compatibilidade entre Python 2 e 3

36

Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 32013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini

Brasília – DFBrasília – DFCentro de Convenções Centro 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

Page 37: (2013-10-02) [PythonBrasil] Compatibilidade entre Python 2 e 3

37

Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 32013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini

Brasília – DFBrasília – DFCentro de Convenções Centro 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 pelo MatPlotLibMatPlotLib

Page 38: (2013-10-02) [PythonBrasil] Compatibilidade entre Python 2 e 3

38

Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 32013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini

Brasília – DFBrasília – DFCentro de Convenções Centro 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)

Page 39: (2013-10-02) [PythonBrasil] Compatibilidade entre Python 2 e 3

39

Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 32013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini

Brasília – DFBrasília – DFCentro de Convenções Centro 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

Page 40: (2013-10-02) [PythonBrasil] Compatibilidade entre Python 2 e 3

40

Compatibilidade entre Python 2 e 3Compatibilidade entre Python 2 e 32013-10-02 – Danilo J. S. Bellini – @danilobellini2013-10-02 – Danilo J. S. Bellini – @danilobellini

Brasília – DFBrasília – DFCentro de Convenções Centro 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