You are currently browsing the category archive for the ‘Python’ category.

Palavras-chave: Python, listagem, cores, zebrado, zebra list

Em aplicações Web é bastante comum exibir grandes listagens em uma página. Para facilitar a leitura dessas listagens, quase sempre utilizamos do artifício de alternar as cores de fundo das linhas exibidas.

O meu amigo Ulysses, mais uma vez (estou até pensando em deixá-lo escrevendo por aqui) deu uma dica excelente para fazer isso, veja:

cores = ["#F5F5F5", "#FFFFFF"]
for n, linha in enumerate(linhas):
   cor_fundo = cores[n % 2]
   # aqui vai o seu código...

Vou aproveitar também essa dica para embutir uma outra dica mais voltada para a “usabilidade”: a diferença de saturação entre uma cor e outra usada no exemplo acima deve ser pequena para tornar esse efeito efetivo.

Palavras-chave: Python, or, in, if, while, condicional, pythonico

Quem está começando no mundo do desenvolvimento Python e não conhece muito a linguagem, costuma criar cláusulas condicionais muito longas utilizando o operador “or”:

if a == "foo" or a == "bar" or a == "baz":
   print a

Imagine o tamanho dessa cláusula quando precisar comparar o valor de “a” com muitos outros valores. Para essas situações você pode usar o operador “in” do Python que verifica se há uma ocorrência do objeto em uma lista:

if a in ["foo", "bar", "baz"]:
   print a

Ficou bem mais simples e legível, não? Esta é a maneira “pythônica” de se montar esse tipo de cláusula condicional.

Essa dica foi sugerida pelo meu amigo Ulysses que me atentou para o fato de que os novatos na linguagem costumam fazer esse tipo de cláusula da forma inadequada.

Palavras-chave: Python, split, tokenizacão, análise léxica, parser, strings, quotes, aspas

O módulo re possui a conveniente função split(), que faz o mesmo que o split() dos strings, mas aceita expressões regulares como separador. Isto pode ser aproveitado para fazer um “parser de pobre” para casos simples, como por exemplo, quebrar um texto em palavras, levando em conta “strings” entre aspas:

 >>> texto="lorem ipsum dolor 'hello world' 'mais texto'' assim'"
 >>> print filter(None,re.split("('(?:[^']|'')*')| ", texto))
['lorem', 'ipsum', 'dolor', "'hello world'", "'mais texto'' assim'"]

O filter() é necessário para remover espaços em branco e Nones que sobram no resultado. Como bônus, strings podem conter ' escapados com ''.

Palavras-chave: testes, unittest, docstring, documentação, testes unitários, rest, docutils

Todo desenvolvedor sabe que fazer testes é superimportante e que fazer documentação também é algo que melhora a qualidade de seus produtos. Mas num primeiro momento, fazer testes é trabalhoso e documentar o nosso código também costuma ser muito chato.

E se a gente conseguisse fazer as duas coisas ao mesmo tempo e obter bons testes e boa documentação? Com o módulo doctest do Python é possível fazer isso. Veja o exemplo abaixo (que foi parcialmente tirado da documentação do módulo):

# -*- coding: utf-8 -*-
import doctest

def fatorial(valor):
    """fatorial(int) -> int
    A função fatorial pode ser usada para calcular
    o fatorial de um número n onde n > 0 vejam os exemplos::
       >>> fatorial(15)
       1307674368000L
       >>> fatorial(-1)
       Traceback (most recent call last):
       ...
       ValueError: valor precisa ser > 0
       >>> fatorial(15.1)
       Traceback (most recent call last):
       ...
       ValueError: valor precisa ser inteiro
    """
    if valor < 0:
        raise ValueError("valor precisa ser > 0")

    if not isinstance(valor, (int,long)):
        raise ValueError("valor precisa ser inteiro")

    if valor:
        return valor * fatorial(valor - 1)
    return 1

if __name__ == '__main__':
    doctest.testmod()

Agora, para rodar nossos testes basta executar esse exemplo:

$ python fatorial.py -v
:
1 items passed all tests:
   3 tests in __main__.fatorial
3 tests in 2 items.
3 passed and 0 failed.
Test passed.

Além de colocar os testes dentro das docstrings também podemos usar arquivos texto convencionais para essa mesma finalidade. A documentação pode usar o formato ReST usado pelos utilitários docutils.

Palavras-chave: userdir, home, homedrive, homepath, arquivo de configuração

Frequentemente precisamos guardar preferências do usuário de nossos programas em algum arquivo de configuração. Em ambientes UNIX/Linux a prática diz que esses arquivos devem ser guardados dentro do diretório $HOME e de preferência como um arquivo (ou diretório) oculto.

Mas usar a variável de ambiente $HOME para obter o diretório não é uma solução muito portável e certamente irá falhar em outros sistemas operacionais, como o Windows.

Para esses casos o módulo os.path disponibiliza a função expanduser() que irá substituir o símbolo ~ pelo caminho completo de onde devemos guardar esses os arquivos de configuração. Veja abaixo um exemplo de uso desta função:

import os.path
print os.path.expanduser("~/.arquivorc")

Rodando esse exemplo em um ambiente UNIX/Linux iremos obter algo parecido com isso:

/home/username/.arquivorc

Já em uma máquina com Windows (XP) teremos:

C:\\Documents and Settings\\username\\.arquivorc

Algumas observações:

  • Em ambientes UNIX/Linux é possível obter o $HOME de outros usuários. Para isso basta usar expanduser("~outro_usuario"). Isso não funcionará no Windows.

  • Não existe um padrão que diga o lugar correto para guardar arquivos de configuração no Windows. O diretório sugerido aqui é aceito mas aparentemente o mais correto seria: C:\Documents and Settings\username\Application Data\meu_programa\config.ini (lembrando sempre que “Application Data” pode ter outro nome em Windows de outros idiomas).

  • A forma 100% correta para achar esse diretório no Windows envolve a procura no “Registry” do Windows, mas isso fugiria do escopo dessa dica.

Palavras-chave: print, stdin, stdout, stderr, erro, dispositivos, entrada/saída

Quando estamos fazendo um programa que roda na linha de comando e precisamos fazer com que esse programa imprima uma mensagem de erro ou alerta, é aconselhável enviar essa mensagem para a saída de erro padrão, conhecida como STDERR.

A linguagem Python disponibiliza para o programador todos os dispositivos de entrada/saída padrão do sistema operacional dentro do módulo sys:

sys.stdin      Entrada padrão (STDIN)
sys.stdout     Saída padrão (STDOUT)
sys.stderr     Saída de erros (STDERR)

O comando print envia as mensagens que serão impressas no terminal para o dispositivo sys.stdout. Neste caso, como podemos enviar mensagens para a saída de erro? De duas maneiras: usando o método .write() do dispositivo ou usando o redirecionamento do comando print. Veja os exemplos:

import sys

# .write()
# Dica: lembre-se de adicionar a quebra-de-linha no final
sys.stderr.write("ERRO: mensagem de erro.\\n")

# redirecionamento
print >>sys.stderr, "ERRO: mensagem de erro."

A sintaxe de redirecionamento é desconhecida de muitos programadores Python, mas é bastante prática e também pode ser usada para escrita de qualquer tipo de arquivo.

Palavras-chave: Unicode, utf8, SQLObject, TurboGears, erro

UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 50: ordinal not in range(128)

Este erro pode ocorrer quando se tenta executar queries que envolvem caracteres Unicode (na query em si ou no resultado) usando SQLObject (o módulo de banco de dados usado no TurboGears).

A solução é forçar o SQLObject a usar UTF-8 internamente e desativar conversões desnecessárias sendo feitas por ele. Para isso modifique sua URI de conexão para algo como:


sqlobject.dburi=
"mysql://root:@localhost:3306/fliki?use_unicode=1&sqlobject_encoding=utf8"

Dependendo da versão do SQLObject pode ser necessário também adicionar o parâmetro charset=utf8 à URI.

Palavras-chave: pacote, módulo, import

Criar um módulo em Python é extremamente simples. Basta apenas criar um arquivo .py dentro de algum diretório listado em sys.path. Alguns desenvolvedores também gostariam de fazer pacotes com módulos em Python. Esses pacotes permitiriam que o programador importasse seus módulos da seguinte maneira:

import meu_pacote.meu_subpacote.modulo
from outro_pacote.outro_subpacote import outro_modulo

Um pacote nada mais é do que um diretório no sistema de arquivos que possui um arquivo __init__.py dentro. Dentro do arquivo __init__.py, deve-se colocar o código de inicialização do pacote, bem como definir a variável __all__, que irá listar todos os símbolos que serão importados no comando from ... import *. No caso em que o arquivo __init__.py fica vazio todos símbolos do pacote serão importados.

Considere a seguinte estrutura:

# meu_pacote/
#    __init__.py -- vazio
#    meu_subpacote/
#       __init__.py -- vazio
#       modulo.py -- imprime "modulo importado"

A partir do diretório atual podemos fazer:

>>> import meu_pacote.meu_subpacote.modulo
modulo importado

Se os arquivos __init__.py não existissem um erro como este aconteceria:

>>> import meu_pacote.meu_subpacote.modulo
Traceback (most recent call last):
  File "", line 1, in ?
ImportError: No module named meu_pacote.meu_subpacote.modulo
Add to Technorati Favorites

Assuntos