|
| 1 | +Title: Sobre o six e como ele ajuda a escrever código compatível com python 2 e 3 |
| 2 | +Date: 2014-05-04 22:21 |
| 3 | +Tags: python, six, compatibility, python3 |
| 4 | +Category: Python |
| 5 | +Slug: sobre-o-six-e-como-ele-ajuda-a-escrever-codigo-compativel-com-python-2-e-3 |
| 6 | +Author: Artur Felipe de Sousa |
| 7 | + |
| 8 | + |
| 9 | + |
| 10 | +### Python 2.x ou python 3.x? |
| 11 | + |
| 12 | +Quem de nós já não se deparou com a seguinte dúvida: Qual versão do |
| 13 | +python devo usar para começar meu projeto? |
| 14 | + |
| 15 | +Há 6 anos, em dezembro de 2008 foi lançada a versão 3.0 do python. Uma versão |
| 16 | +polêmica, a primeira incopatível com suas anteriores (2.x). A intenção era de |
| 17 | +corrigir antigas "chatices" que vinham incomodando o Guido van Rossum e a |
| 18 | +comunidade, e remover coisas desnecessárias. Alguns exemplos mais comuns: |
| 19 | + |
| 20 | +* Todas as strings são unicode **str()** |
| 21 | +* O comando print virou a built-in **print()** |
| 22 | +* Iterators ao invés de listas: **map(), filter(), zip()** e **range()** |
| 23 | +* Tipo long passou a ser somente int |
| 24 | +* Todas as classes são new-style |
| 25 | + |
| 26 | +Para mais detalhes [https://docs.python.org/3.0/whatsnew/3.0.html](https://docs |
| 27 | +.python.org/3.0/whatsnew/3.0.html). |
| 28 | + |
| 29 | +O python 3 já está na versão 3.4 e vem sendo cada vez mais suportado por |
| 30 | +bibliotecas e frameworks mais populares tais como: |
| 31 | + |
| 32 | +* Django (1.5+) |
| 33 | +* Pyramid (1.3a1+) |
| 34 | +* Flask |
| 35 | +* SqlAlchemy |
| 36 | + |
| 37 | +Todas essas ferramentas tiveram a mesma preocupação que deve estar passando |
| 38 | +pela sua cabeça agora: Como migrar ou criar código compatível o máximo possível |
| 39 | +entre essas versões? |
| 40 | + |
| 41 | +É aí que entra a biblioteca six. |
| 42 | + |
| 43 | +### Six? |
| 44 | + |
| 45 | +O six é uma biblioteca de compatibilidade entre o python 2 e 3. O nome "six" |
| 46 | +surgiu da grande sacada do Benjamin Petersons, 2 * 3 == 6, muita imaginação |
| 47 | +não? Todo o código do six está contido em apenas um arquivo python |
| 48 | +[six.py](https://bitbucket.org/gutworth/six/src/a497bee85dd833681574672b5a2ec29 |
| 49 | +6e33c525c/six.py?at=default "Repositório do six"). |
| 50 | + |
| 51 | +Para instalar o six, basta usar o pip: |
| 52 | + |
| 53 | + :::python |
| 54 | + pip install six |
| 55 | + |
| 56 | +Vamos começar com um exemplo de código que funciona somente na versão 2.7.5: |
| 57 | + |
| 58 | + :::python |
| 59 | + if isinstance(u'Python 2 compatible', unicode): |
| 60 | + print 'is unicode' |
| 61 | + |
| 62 | +O primeiro erro observado é o comando print que gera um erro de sintaxe, o |
| 63 | +seguinte é o identificador unicode que não existe mais no python 3 (passou a |
| 64 | +ser str somente). |
| 65 | + |
| 66 | +Uma versão deste código que funciona no python 3.4.0 seria: |
| 67 | + |
| 68 | + :::python |
| 69 | + if isinstance(u'Python 3 compatible', str): |
| 70 | + print('is unicode') |
| 71 | + |
| 72 | +Utilizando o six para compatibilizar o código, teríamos: |
| 73 | + |
| 74 | + :::python |
| 75 | + import six |
| 76 | + if isinstance(u'Python 2 and 3 compatible', six.string_types): |
| 77 | + six.print_('is unicode') |
| 78 | + |
| 79 | +No exemplo acima foi utilizada a constante **six.string_types**. Essas |
| 80 | +constantes são normalmente utilizadas como segundo argumento da função |
| 81 | +**isinstance()**. [Veja mais delas](https://pythonhosted.org/six/#constants). |
| 82 | + |
| 83 | +No python 3 alguns atributos e metódos foram substituídos ou removidos de |
| 84 | +alguns tipos de estrutura de dados. Os métodos **iterkeys(), itervalues(), |
| 85 | +iteritems()** e **iterlists()**, por exemplo, foram renomeados dos dicionários |
| 86 | +por **keys(), values(), items()** e **lists()** respectivamente. |
| 87 | + |
| 88 | + :::python |
| 89 | + # Python 2.7.5 |
| 90 | + > my_info = dict(name='Artur Sousa', age=29) |
| 91 | + > my_info.itervalues() |
| 92 | + <dictionary-valueiterator object at 0x10738e680> |
| 93 | + > my_info.values() |
| 94 | + [29, 'Artur Sousa'] |
| 95 | + |
| 96 | + # Python 3.4.0 |
| 97 | + > my_info = dict(name='Artur Sousa', age=29) |
| 98 | + > my_info.values() |
| 99 | + dict_values([29, 'Artur Sousa']) |
| 100 | + |
| 101 | +Versões compatíveis destes métodos podem ser encontradas no six: |
| 102 | + |
| 103 | + :::python |
| 104 | + # Python 2.x 3.x |
| 105 | + > import six |
| 106 | + > my_info = dict(name='Artur Sousa', age=29) |
| 107 | + > six.itervalues(my_info) |
| 108 | + <dictionary-valueiterator object at 0x10738e680> |
| 109 | + > six.iterkeys() |
| 110 | + <dict_keyiterator object at 0x10b2f4638> |
| 111 | + |
| 112 | +[Dentre outras...](https://pythonhosted.org/six/#object-model-compatibility) |
| 113 | + |
| 114 | +No python 3 algumas libs foram reorganizadas da biblioteca padrão. O |
| 115 | +**HTMLParser** por exemplo virou **html.parser**. Para isso o six oferece o |
| 116 | +módulo moves. |
| 117 | + |
| 118 | + :::python |
| 119 | + from six.moves import html_parser # 2.x: HTMLParser 3.x: html.parser |
| 120 | + from six.moves import cPickle # 2.x: cPickle 3.x: pickle |
| 121 | + |
| 122 | +Uma tabela de compatibilidade de métodos e atributos pode ser vista |
| 123 | +[aqui](https://pythonhosted.org/six/#module-six.moves). |
| 124 | + |
| 125 | +Esta foi apenas uma parte das funcionalidades que o six oferece para garantir |
| 126 | +o funcionamento de códigos escritos nas versões 2 e 3 do python. |
| 127 | + |
| 128 | +O Django utiliza o six a partir da versão 1.5. Veja um exemplo de uso: |
| 129 | + |
| 130 | + :::python |
| 131 | + # django.contrib.admin.helpers.py - Django 1.7b3 |
| 132 | + class AdminErrorList(forms.utils.ErrorList): |
| 133 | + """ |
| 134 | + Stores all errors for the form/formsets in an add/change stage view. |
| 135 | + """ |
| 136 | + def __init__(self, form, inline_formsets): |
| 137 | + super(AdminErrorList, self).__init__() |
| 138 | + |
| 139 | + if form.is_bound: |
| 140 | + self.extend(list(six.itervalues(form.errors))) |
| 141 | + for inline_formset in inline_formsets: |
| 142 | + self.extend(inline_formset.non_form_errors()) |
| 143 | + for errors_in_inline_form in inline_formset.errors: |
| 144 | + self.extend(list(six.itervalues(errors_in_inline_form))) |
| 145 | + |
| 146 | +Então galera, esse foi um artigo introdutório sobre o six, mostrando alguns |
| 147 | +casos de uso e um pouco das diferenças entre o python 2 e 3. Espero que vocês |
| 148 | +tenham gostado. Fiquem à vontade para enviar dúvidas, sugestões ou críticas. |
| 149 | + |
| 150 | +Até mais... |
0 commit comments