Planeta PythonBrasil

July 08, 2008

Rodrigo Amaral

Python cada dia mais próximo do NetBeans

Há algum tempo a Sun contratou dois pythonistas renomados para aproximá-la da linguagem. Uma conseqüência natural dessa aproximação seria o suporte a Python em sua IDE NetBeans . Na verdade, a iniciativa já vinha de antes do recrutamento de Ted Leung e Frank Wierzbicki . O projeto NBPython , iniciado por Allan Davis , ganhou o auxílio dos dois novos colaboradores e uma versão inicial já está disponível para quem quiser testar. Por enquanto, o plugin só funciona em nightly builds , já que está em fase inicial de desenvolvimento.

Outra boa notícia vinda da Sun é o lançamento de seu Python Developer Center . O site ainda tem pouco conteúdo, mas não deixa de ser mais uma oportunidade de divulgar Python e seus frameworks para um público que, via de regra, ainda não despertou para o fato de que existe vida além do Java.

Referência: Python in NetBeans: NBPython

por Rodrigo Amaral em 08 de July de 2008 às 23:24

Leonardo Gregianin

Elcio Luiz Ferreira

Integrando o Vim com ferramentas externas

Depois que comecei a usar o Vim nas palestras em que eu escrevo código, muita gente começou a me escrever com dúvidas sobre o editorzinho. Apesar de eu dizer nas palestras que Vim é complicado, parece que o pessoal não tem medo. E a dúvida mais freqüente é sobre a integração entre o Vim e ferramentas externas, principalmente o txt2tags.

Faz parte da filosofia Unix que um programa seja facilmente integrado a outros através de interfaces de texto, e o Vim implementa isso muito bem. Para começar, abra o Vim e execute:

:!ls

Você vai ver que o Vim vai executar o comando ls. Então guarde isso, o sinal de exclamação (!) executa comandos externos. Há duas maneiras de fazer o Vim falar com esses comandos. A primeira é mandar o Vim ler a entrada do comando. Digite:

:r!ls

Você vai notar que o Vim vai executar o comando ls e colocar o conteúdo no buffer de edição. A outra maneira de fazer o Vim falar com os programas externos é selecionar texto. Aperte i para ir para o modo de edição e digite:

zebra
tesoura
banana
macaco
felicidade
abacate

Ao terminar de digitar, pressione ESC para voltar ao modo de comando, em seguida SHIFT+V para ir para o modo de seleção de linha e selecione todo o bloco. Com o bloco selecionado, digite:

:!sort

O vim vai colocar, antes do comando, os sinais de seleção ','>. Não se preocupe, apenas digite o comando e aperte ENTER. Você vai ver que o Vim vai executar o comando sort do sistema operacional, passando como entrada o texto selecionado, e vai substituir esse texto pela saída do comando. Isso, ao final, vai te dar a lista ordenada, assim:

abacate
banana
felicidade
macaco
tesoura
zebra

Usando essa interface simples você pode fazer o Vim falar com qualquer programa Unix.

txt2tags

O programa que eu tenho usado durante as palestras e mais tem deixado as pessoas curiosas é o txt2tags, desenvolvido pelo Aurélio Marinho. O programa está nos repositórios do Debian, então se você usa Debian ou Ubuntu, pode instalá-lo com o comando:

sudo apt-get install txt2tags

O txt2tags lê as primeiras linhas de texto que recebe como títulos do documento. Além disso, precisaremos de várias opções de linha de comando, o que não é conveniente de se digitar. Então vamos criar um shell script para guardar essas opções e fornecer ao txt2tags linhas de cabeçalho de mentirinha. Eu criei um arquivo chamado tags dentro do diretório /usr/local/bin, com permissão de execução (chmod +x) e o seguinte conteúdo:

#!/bin/bash
(echo "
 
 
 
 
 
" && cat ) | txt2tags -t xhtml --infile=- --no-headers

Em seguida, basta abrir o Vim e digitar, por exemplo:

= Aprenda Online =
A [Visie http://visie.com.br/] oferece cursos de Ajax, Javascript e Tableless.

Em seguida selecione essas duas linhas e execute:

:!tags

Pronto, HTML instantâneo.

por Elcio em 08 de July de 2008 às 17:12

Devlog

Protocol Buffers

http://google-opensource.blogspot.com/2008/07/protocol-buffers-googles-data.html

É o nome do mais novo projeto do google disponibilizado para a comunidade do código livre.

Segundo a descrição no anúncio do projeto, ele nasceu da necessidade de serializar dados e trocar esses dados serializados pela rede de forma eficiente. Já nasceu com versões para Java, C++, ou Python.

Você define uma descrição de um objeto, um arquivo .proto, e o compilador gera o código necessário para acesso na linguagem que você escolher, dentre as três suportadas.

Segundo a documentação: "Protocol buffers are now Google's lingua franca for data – at time of writing, there are 48,162 different message types defined in the Google code tree across 12,183 .proto files. They're used both in RPC systems and for persistent storage of data in a variety of storage systems."

por Walter Cruz em 08 de July de 2008 às 14:36

Notícias da PyCon

Chamada de trabalhos para a PyConBrasil 2008 se encerra nesse domingo

Ainda dá tempo de você enviar a sua proposta. A PyConBrasil 2008 ocorrerá no Rio de Janeiro, de 18 a 20 de setembro.

por marcoandre em 08 de July de 2008 às 12:21

July 06, 2008

Rodolpho Eckhardt

MungeFile

Depois que analisamos a função MungeWord e chegamos à conclusão que todas as implementações apresentadas possuem desempenhos similares, voltamos nossa atenção para a função MungeFile, pois a diferença na performance geral do programa deve ser consequência dela.

Lembramos que as quatro implementações que sugeri foram:

A primeira - que utiliza índices e slices:

def MungeFile(all_data):
  result = []
  index = 0
  while index < len(all_data):
    while index < len(all_data) and not all_data[index].isalpha():
      result.append(all_data[index])
      index += 1
    end = index + 1
    while end < len(all_data) and all_data[end].isalpha():
      end += 1
    result.append(MungeWord(all_data[index:end]))
    index = end
  final = “”.join(result)
  return final

A segunda - que utiliza pop:

all_data = list(all_data)
  result = []
  if len(all_data) <= 2:
    return result
  char = all_data.pop(0)
  while all_data:
    word = []
    while all_data and char.isalpha():
      word.append(char)
      char = all_data.pop(0)
    result.append(MungeWord(”.join(word)))
    while all_data and not char.isalpha():
      result.append(char)
      char = all_data.pop(0)
  final = “”.join(result)
  return final

A terceira, que quebra o texto em palavras, utilizando expressão regular:

def MungeFile(all_data):
  regex = re.compile(r"(\W+)", re.UNICODE)
  words = regex.split(all_data)
  result = []
  while words:
    word = words.pop(0)
    result.append(MungeWord(word))
  final = “”.join(result)
  return final

A quarta, que realiza uma função de substituição sobre os acertos de uma expressão regular:

def MungeFile(all_data):
  regex = re.compile(r"\w+", re.UNICODE)
  all_data = regex.sub(MungeWord, all_data)
  final = "".join(all_data)
  return final

E, além dessas, temos a implementação que o Walter desenvolveu e postou aqui. A principal diferença é que a solução dele utiliza o módulo shlex:

def munge(text):
  t = shlex.shlex(text, posix=False)
  t.quotes = "'"
  t.whitespace = ""
  s = (munge_word(word) for word in t)
  final = "".join(s)
  return final

Para testar as cinco funções, gerei dinamicamente um texto com quantidade de palavras variando de 1 a 5000. Cada palavra possui 9 letras.

Para textos com menos de 1300 palavras, os cinco algoritmos apresentaram tempo de execução inferior a 0,1 segundo. A partir daí, no entanto, já se nota que a segunda implementação apresenta um aumento razoável em relação às demais.

Abaixo está um gráfico dos resultados - infelizmente não consegui inserir a legenda na própria imagem, mas é:

  • Azul: primeira solução
  • Verde: segunda solução
  • Vermelho: terceira solução
  • Amarelo: quarta solução
  • Azul claro: quinta solução (do Walter)

MungeFile

Não é difícil entender o porque do aumento maior da segunda implementação: enquanto as três últimas trabalham com a separação e tratamento de palavras, a segunda varre a entrada letra por letra, similar a primeira, mas utiliza pop na primeira posição de uma lista. Está aí a lição :P pop funciona muito bem para os últimos elementos de uma lista, mas quanto mais nos aproximamos do início, pior o desempenho.

Vamos verificar isso. Vou alterar a segunda implementação para o seguinte:

def MungeFile(all_data):
  all_data = list(all_data)
  all_data.reverse()
  result = []
  if len(all_data) <= 2:
    return result
  char = all_data.pop()
  while all_data:
    word = []
    while all_data and char.isalpha():
      word.append(char)
      char = all_data.pop()
    result.append(MungeWord(”.join(word)))
    while all_data and not char.isalpha():
      result.append(char)
      char = all_data.pop()
  final = “”.join(result)
  return final

Notem que eu simplesmente inverti a ordem dos elementos da lista e utilizei pop nos últimos elementos (que eram os primeiros). Veja o resultado agora:

MungeFile2

Impressionante! Saber como os métodos e as estruturas de dados funcionam, bem como os módulos disponíveis, é de extrema importância quando otimizando algoritmos. A simples inversão de uma lista representou ganhos de 89,5%, nos casos de textos com 5000 palavras.

O melhor método ainda parece ser utilizar substituição em caso de match por expressão regular. Durante meus testes encontrei um “fenômeno” interessante que ocorre com o shlex ao processar textos muito longos (>100M). Ainda estou investigando as causas e postarei os resultados em breve :)

Beijos e abraços!

ps: lembrando que as soluções que utilizam expressões regulares não são completamente válidas para o problema (estamos embaralhando pontuação e números, o que não seria aceito).

por rootguy em 06 de July de 2008 às 06:14

July 05, 2008

Marcos Daniel

Mais DrawingArea, Orientação a objetos e herança (e glade)


Este artigo mistura um pouco de tudo o que foi visto nos artigos anteriores:

Criando uma simples janela em PyGTK
Criando uma simples janela em PyGTK - parte II
DrawingArea - Desenhando na tela com PyGTK
Orientação a Objetos com python
Orientação a Objetos - Herança

Como aqui vamos usar o Glade, recomendo também uma visita ao blog do OgMaciel:

Vídeo Aula: Programando com Python e Glade

Vídeo Aula: Trabalhando com o Glade

Não deixe de ver também Mantendo A Sanidade Com O Glade.

Neste artigo vamos criar um programa em que você pode desenhar um polígono desenhando com o mouse.

Para isso, vamos estender a classe gtk.DrawingArea através da herança. Nossa classe estendida vai ser um DrawingArea com recursos que nós vamos adicionar.

Paralelamente, vamos fazer uma janela com o glade, um código que vai exibir a janela inserindo nela a nossa classe filha de DrawingArea.

A nossa classe tela herdando de DrawingArea:


import gtk

# do modulo gtk, importamos DrawingArea e vamos chamar de 'DA'
from gtk import DrawingArea as DA

class tela(DA):
    def __init__(self):
        # executanto o construtor da classe pai (DrawingArea)
        DA.__init__(self)

Agora temos uma classe que faz tudo o que um DrawingArea faz. Podemos acrescentar recursos a ela.

Enquanto isso, vamos fazer a GUI no glade:
- crie uma janela;

- adicione uma “Caixa Vertical” (Vbox) com três itens;

- adicione um Rótulo (Label) na primeira seção da Caixa Vertical;

- em Empacotamento, mude para “não” as opções Expandir e Preencher;

- adicione um botão e em Geral mude o nome para ‘botão1′ (é, poderia ter ficado Button1 mesmo);

- em Empacotamento, mude para “não” as opções Expandir e Preencher;

- no espaço do meio, adicione uma ‘Porta de Visualização’ (ViewPort) ;

- mude o nome da ViewPort para ‘caixatela’

- explore as outras opções de configuração dos widgets

Sua janela deve ficar quase assim:


Voltemos à nossa classe.

O nosso widget será usado da seguinte forma:

Você pressiona o botão esquerdo do mouse sobre o widget e mantém pressionado. Arrasta então o ponteiro do mouse pela tela; uma linha será desenhada por onde passar o ponteiro. Ao soltar o botão do mouse, a linha se fechará em um polígono.

Ao Rolar a ‘rodinha’ do mouse, os últimos pontos do polígono serão removidos; continue rolando a rodinha que o polígono desaparecerá.

Temos então três eventos envolvidos na criação do desenho: botão pressionado, movimento do mouse e botão solto (‘button-press-event’, ‘button-release-event’ e ‘motion-notify-event’ ). Um quarto evento, o de rolagem da rodinha (’scroll-event’ ), está envolvido na operação de remover pontos do polígono.


class tela(DA):
    def __init__(self):
        DA.__init__(self)
        self.definecores()

        # atributo que determina se o botão está pressionado
        self.apertou=False

        # conectando o expose-event a uma função
        # que vai pedir que a tela seja redesenhada
        self.connect('expose-event',self.expose)

        # adicionando os eventos de mouse
        self.add_events(gtk.gdk.BUTTON_PRESS_MASK |
            gtk.gdk.BUTTON_RELEASE_MASK |
            gtk.gdk.MOTION_NOTIFY |
            gtk.gdk.POINTER_MOTION_MASK
            )

        # conectando cada evento à sua função correspondente

        # botão de mouse pressionado
        self.connect('button-press-event',self.clica)
        # soltando o botão
        self.connect('button-release-event',self.solta)
        # movimento de mouse
        self.connect('motion-notify-event',self.arrasta)
        # rolando a 'rodinha'
        self.connect('scroll-event',self.rolou)

        # criando uma lista vazia
        # que vai conter os pontos da linha a ser desenhada
        # ou o polígono
        # cada ponto será uma tupla
        # com as coordenadas (x,y)
        self.linha=[]

Olhe o código acima, nas linhas 23, 25, 27 e 29. Quatro funções terão que ser definidas. Vejamos o que cada uma deve fazer:

- self.clica

  • mudar a variável self.apertou para True
  • adicionar o primeiro ponto (as coordenadas do clique) à lista self.linha

- self.arrasta

  • se self.apertou é True, adiciona mais um ponto À lista e desenha o último segmento.

- self.solta

  • mudar a variável self.apertou para False

- self.rolou

  • remover o último ponto da lista e mandar a tela ser redesenhada

    def solta(self, tela, evento):
        self.apertou=False
        self.desenha()

    def clica(self, tela, evento):
        if evento.button==3:
            self.linha.pop()
            return
        self.linha.append((evento.x,evento.y))
        self.apertou=True

    def rolou(self,tela,evento):
        try:
            self.linha.pop()
            self.desenha()
        except:
            pass

    def arrasta(self,tela,evento):
        if self.apertou:
            self.linha.append((evento.x,evento.y))

Movendo o mouse com o botão pressionado

Após soltar o botão

O código completo da classe:


import gtk
from gtk import DrawingArea as DA

class tela(DA):
    def __init__(self):
        DA.__init__(self)
        self.definecores()

        self.apertou=False
        self.connect('expose-event',self.expose)
        self.add_events(gtk.gdk.BUTTON_PRESS_MASK |
            gtk.gdk.BUTTON_RELEASE_MASK |
            gtk.gdk.MOTION_NOTIFY |
            gtk.gdk.POINTER_MOTION_MASK
            )
        self.connect('button-press-event',self.clica)
        self.connect('button-release-event',self.solta)
        self.connect('motion-notify-event',self.arrasta)
        self.connect('scroll-event',self.rolou)
        self.linha=[]

    def definecores(self):
        self.verde=gtk.gdk.Color(0,48255,0,0)
        self.preto=gtk.gdk.Color(0,0,0,0)
        self.branco=gtk.gdk.Color(65535,65535,65535,0)
        self.vermelho=gtk.gdk.Color(65535,0,0,0)
        self.amarelinho=gtk.gdk.Color(35535,65333,15000,0)
        self.outra=gtk.gdk.Color(0,65535,65535,0)
        self.azul=gtk.gdk.Color(0,0,65535,0)

    def desenhaultimo(self):
        if len(self.linha)>1:
            x1=int(self.linha[-2][0])
            y1=int(self.linha[-2][1])
            x2=int(self.linha[-1][0])
            y2=int(self.linha[-1][1])

            self.gc.set_rgb_fg_color(self.vermelho)
            self.window.draw_line(self.gc,x1,y1,x2,y2)

            self.gc.set_rgb_fg_color(self.preto)
            self.window.draw_rectangle(self.gc,False,x1-1,y1-1,2,2,)
            self.window.draw_rectangle(self.gc,False,x2-1,y2-1,2,2,)

    def solta(self, tela, evento):
        self.apertou=False
        self.desenha()

    def clica(self, tela, evento):
        if evento.button==3:
            self.linha.pop()
            return
        self.linha.append((evento.x,evento.y))
        self.apertou=True

    def rolou(self,tela,evento):
        try:
            self.linha.pop()
            self.desenha()
        except:
            pass

    def arrasta(self,tela,evento):
        if self.apertou:
            self.linha.append((evento.x,evento.y))
            self.desenhaultimo()

    def apaga(self):
        for pt in self.linha:
            print pt
        self.linha=[]
        self.desenha()

    def desenha(self):
        a,b,c,d = self.get_allocation()
        self.gc.set_rgb_fg_color(self.branco)
        self.window.draw_rectangle(self.gc,True,0,0,c-1,d-1)

        if len(self.linha)>0:
            self.gc.set_rgb_fg_color(self.amarelinho)
            self.window.draw_polygon(self.gc,True, self.linha)
            self.gc.set_rgb_fg_color(self.preto)
            self.window.draw_polygon(self.gc,False, self.linha)

        self.gc.set_rgb_fg_color(self.preto)
        self.window.draw_rectangle(self.gc, False,2,2,c-4,d-4 )
        for pt in self.linha:
            self.window.draw_rectangle(self.gc, False,pt[0]-1, pt[1]-1,2,2)

    def expose(self,tela, evento):
        self.gc=self.get_style().fg_gc[gtk.STATE_NORMAL]
        self.gc.set_rgb_fg_color(self.branco)
        self.desenha()

Para entender as operações de desenho, veja o artigo anterior: DrawingArea - Desenhando na tela com PyGTK

Salve este código como desenha.py

Salve seu projeto no Glade como parapintar.glade

E execute o código abaixo, que vai reunir tudo:


#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Código parcialmente reaproveitado
do código exemplo do OgMaciel
em http://blog.ogmaciel.com/?p=413
"""

import desenha
try:
    import pygtk
    pygtk.require( "2.0" )
except:
    pass
try:
    import gtk
    import gtk.glade
except:
    sys.exit(1)

class Janelao(object):
    """
    Janela criada com o Glade
    """

    def __init__(self):
        self.xml = gtk.glade.XML( "parapintar.glade" )
        self.xml.signal_autoconnect(self)

        self.mainWindow = self.xml.get_widget( 'window1' )
        self.mainWindow.set_title( "Pintor" )

        # puxando a ViewPort criado no glade
        self.caixa=self.xml.get_widget( 'caixatela' )
        self.mainWindow.connect('destroy', gtk.main_quit)

        self.botao = self.xml.get_widget( 'botao1' )

        # criando uma instancia do nosso objeto
        self.tela=desenha.tela()
        #inserindo nosso objeto na viewport
        self.caixa.add(self.tela)

        self.botao.connect("clicked",self.apagar_tela)
        self.tela.show()
        self.mainWindow.show_all()

    def apagar_tela(self,botao):
        self.tela.apaga()

if __name__ == "__main__":
    w = Janelao()
    gtk.main()

por medeubranco em 05 de July de 2008 às 12:43

Brincando de arvore binária com Python


De repente me deu vontade de fazer uma árvore binária em python. Não sei por que, nem para quê, mas deu vontade.

Usei um exemplo que creio ter visto no livro “C A linguagem de Programação” de Brian Kernighan e Dennis Ritchie : contagem de palavras em um texto.

O livro fala de árvores binárias como alternativa, neste problema de contagens de palavras, à pesquisa binária. Numa pesquisa binária, pressupomos que a lista de valores está previamente ordenada. Isso não deve ocorrer com as palavras de um texto qualquer. Não sabemos nem mesmo a quantidade de palavras que podem estar contidas nesse texto, de modo que pode não ser muito eficiente rodar previamente um algoritmo de ordenação. A salvação então é a tal árvore binária.

No meu código abaixo, criei uma classe (arvbin) para representar os nós da árvore. Os atributos da classe são: a palavra, o contador de ocorrências da palavra, um apontador para a palavra menor e outro para a maior:


class arvbin:
    def __init__(self, Valor):
        self.Menor=None  #apontador para a palavra menor
        self.Maior=None  #apontador para a palavra maior
        self.conta=1     #conttador de ocorrências
        self.valor=Valor #a palavra

O método add percorre a árvore até achar um lugar apropriado para a palavra a ser adicionada. Em cada nó, ele compara a nova palavra à palavra do nó. Se forem iguais, simplesmente incrementa o contador e retorna; se for maior, verifica se ja existe um nó maior no apontador sef.Maior; não tendo, adiciona um novo nó ao apontador “self.Maior”, com a palavra nova. Se já existe o nó maior, repete a operação, agora já no nó maior. Se a nova palavra for menor, dá-se a mesma operação, só que a partir do apontador self.Menor.

O método busca percorre a árvore buscando um nó que contenha determinada palavra.

O método ordena percorre recursivamente a árvore e retorna uma lista ordenada com as palavras.


#! /usr/bin/env python
# -.- encoding: utf-8 -.-

class arvbin:
    def __init__(self, Valor):
        self.Menor=None
        self.Maior=None
        self.conta=1
        self.valor=Valor

    def add(self,valor):
        if valor>self.valor:
            self.addmaior(valor)
        elif valor<self.valor:
            self.addmenor(valor)
        else:
            self.conta=self.conta+1

    def addmenor(self,valor):
        if self.Menor:
            self.Menor.add(valor)
        else:
            self.Menor=arvbin(valor)

    def addmaior(self,valor):
        if self.Maior:
            self.Maior.add(valor)
        else:
            self.Maior=arvbin(valor)

    def busca(self,valor):
        if valor>self.valor:
            if self.Maior:
                return self.Maior.busca(valor)
            else :
                return None
        elif valor<self.valor:
            if self.Menor:
                return self.Menor.busca(valor)
            else :
                return None
        else:
            return self

    def ordena(self):
        listamenor=[]
        listamaior=[]
        if self.Menor:
            listamenor=self.Menor.ordena()
        if self.Maior:
            listamaior=self.Maior.ordena()
        return listamenor + [ (self.valor, self.conta) ] + listamaior 

Para testar meu código, adicionei o trecho abaixo. Este código supõe que já existe um arquivo “/tmp/texto” contendo as palavras da nossa brincadeira. Dá para criar um arquivo assim simplesmente copiando um grande texto na web.


if __name__ == '__main__':
    texto=open('/tmp/texto','r' )
    a=texto.read()

    remover=[ '.',',',';',':','?','!','(',')','\'','"' ]
    for remova in remover:
        a=a.replace(remova,'' )

    a=a.replace('\n',' ' )

    a=a.split()
    raiz=arvbin(a[-1] )
    a.pop()
    for palavra in a:
        raiz.add(palavra.upper())
    for palavra in raiz.ordena():
        print palavra[1], palavra[0]

    achei = raiz.busca('não' )
    if achei:
        print achei.valor, achei.conta

por medeubranco em 05 de July de 2008 às 03:18

July 04, 2008

Elton Luís Minetto

Eu quero trabalhar nessa empresa

No meio dos 120 (sério) feeds que leio diariamente (na verdade várias vezes ao dia) encontrei o site desta empresa: Carsonfied

Eles são uma empresa de desenvolvimento na Inglaterra, que trabalham com Django, Rails, Symfony, etc. Mas o mais interessante é a página de vagas de emprego. Olha como eles se descrevem (tradução resumida e alterada):

“… Não somos uma empresa normal :-) Alguns benefícios da vaga:

Semana de 4 dias(O escritório é fechado nas Sextas-feiras). Seu próprio iPhone, monitor de 23 ”, cadeira confortável e MacBook Pro. Bons salários.

Trabalhar na Carsonified não é apenas um trabalho - é um estilo de vida. Nós queremos que você ame trabalhar aqui, então fornecemos o melhor kit do mercado

….

Viu? É disso que eu falo! Melhor do que o Google.

Imagino as pessoas que trabalham lá: Papai Noel (Programador), Coelho da Páscoa (Designer), Capitão Nascimento (Gerente de Projetos)…

Será que isso existe mesmo?

por elm em 04 de July de 2008 às 23:29

Marcos Petry

Proposta do TCC Aprovada!

Acabei de receber um "OK" para minha proposta do meu trabalho de conclusão do curso de graduação!!

A idéia basicamente é criar um gerador de código para o framework Django a partir de modelos UML, algo como o archgenXML mas com algumas técnicas de compiladores (GLC's, Analisadores Léxicos, Sintaticos, etc...)

Para quem quiser mais informações, o link para proposta está publico no Google Docs
http://docs.google.com/Doc?id=d7zxc7q_71rbmszjdd

ahh e também...qualquer ajuda é bem vinda! hehe

por Marcos Daniel Petry (noreply@blogger.com) em 04 de July de 2008 às 09:37

Marcos Daniel

Definindo a codificação em um código python


Imagino que você chegou até este artigo porque, ao executar seu código em python, obteve o seguinte erro:

SyntaxError: Non-ASCII character ‘\xc3′ in file <arquivo> on line <numero de linha>, but no encoding declared; see http://www.python.org/peps/pep-0263.html for details

Sei que você está com um tanto de pressa para resolver seu problema; se é esse o caso, insira no seu código, na primeira ou segunda linha, o código abaixo:


# -*- coding: utf-8 -*-

Pronto, seu problema já deve estar resolvido.

Se tiver um pouquinho mais de tempo, vamos juntos tentar entender o que foi que aconteceu.

Primeiro vamos analisar a mensagem de erro. Meu inglês trôpego me permitiu chegar à seguinte tradução da mensagem de erro:

Erro de sintaxe: no arquivo <nome de arquivo.py>, na linha <numero da linha>, tem um caractere não ASCII (’\xc3′), mas não foi declarada nenhuma codificação de caracteres no seu arquivo fonte.

Dê uma olhadinha em http://www.python.org/peps/pep-0263.html para mais detalhes.

Bem, para nós que não somos bilíngües, qualquer tradução capenga vai bem, até mesmo a minha. ;)

Entendi que você colocou um caractere inexistente na tabela ASCII, usada pelo interpretador python ao analisar o código fonte, e esqueceu-se de avisar ao interpretador para usar outra tabela.

O link sugerido na mensagem de erro nos leva à pagina do Python Enhancement Proposals (PEPs) 0263 - pep-0263 (Propostas de Melhoria para o Python, na minha tradução).

Olhando nesta página, obtive as seguintes informações:

  • a pep-0263 propõe introduzir uma sintaxe para declarar a codificação usada no arquivo fonte.
  • na versão 2.1 do python, o único jeito de escrever ‘literais’ Unicode era ranheta demais.
  • neste ‘pep’ é proposto usar um comentário especial no topo da linha par indicar o ‘encoding’ usado.
  • o interpretador python irá usar ASCII como codificação se nenhuma outra for informada

O documento indica pelo menos três formas de se indicar a codificação:
# coding=<encoding name>

ou, (usando formatos reconhecidos pelos editores mais populares):

#!/usr/bin/python
# -*- coding: <encoding name> -*-

ou

#!/usr/bin/python
# vim: set fileencoding=<encoding name> :

Testei as três formas e funcionou - uso o editor gvim. Testei também substituir utf-8 por iso8859-1, e o interpretador não reclamou.

por medeubranco em 04 de July de 2008 às 00:38

July 03, 2008

Devlog

Mais Text Munger

Whitespace, punctuation, numbers -- anything that isn't a word -- should also remain unchanged.

Ou seja, minha implementação anterior está fundamentalmente errada ;)

E eu só li essa parte do enunciado depois do comentário do Rodolpho.

Mas é fácil de resolver, usando o shlex mesmo:


import sys
import shlex

from random import shuffle

def munge(text):
    t = shlex.shlex(text, posix=False)
    t.quotes = "'"
    t.whitespace = ""
    #print(list(t))
    s = (munge_word(word) for word in t)
    print("".join(s))

def munge_word(aword):
    s = list(aword)
    first = s.pop(0)
    try:
      last = s.pop()
    except IndexError:
        return aword
    shuffle(s)
    return first + ''.join(s) + last

try:
  s = open(sys.argv[1]).read()
  munge(s)
except IndexError:
  print("Usage: munge.py file")
 

por Walter Cruz em 03 de July de 2008 às 20:15

Rodolpho Eckhardt

MungeWord

Primeiro vamos analisar então a função MungeWord que mencionamos no post anterior. Há diversas formas de implementar o que queremos (a primeira e última letras da palavra devem ficar intactas, mas as demais ser embaralhadas) e vou analisar os dois dos modos que testei e uma mistura de ambos. Utilizando índices e slices:

def MungeWord(word):
  if not word or not word[0].isalpha() or len(word) <= 2:
    return word
  middle = list(word[1:-1])
  random.shuffle(middle)
  return ”.join((word[0], ”.join(middle), word[-1]))

Utilizando pop:

def MungeWord(word):
  if len(word) <= 2:
    return word
  word = list(word)
  first = word.pop(0)
  last = word.pop()
  random.shuffle(word)
  return ''.join((first, ''.join(word), last))

E uma mistura de pop e slices:

def MungeWord(word):
  if len(word) <= 2:
    return word
  first = word[0]
  word = list(word)
  last = word.pop()
  middle = word[1:]
  random.shuffle(middle)
  return ”.join((first, ”.join(middle), last))

Comparando a performance das três funções para tamanhos reais de palavras (menos de 100 letras, por exemplo), a diferença entre elas fica em menos de 0,00001 segundo. Então não há motivos “reais” para dar preferência por uma específica - escolha a mais legível, se quiser; eu, pessoalmente, prefiro pop (a segunda implementação).

Mas por que parar por aí? Vamos levar ao extremo, considerando a existência de palavras com milhares de letras. Um gráfico para mostrar o resultado:

MungeWord

Bom, fica claro que, independente do gosto por uma ou outra implementação, o tempo de execução não é afetado, mesmo com palavras gigantes.

Depois retornarei ao assunto para tratar do consumo de memória e da MungeFile também. :)

Beijos e abraços!

por rootguy em 03 de July de 2008 às 16:36

Insônia novamente

Apesar de estar morrendo de cansaço, não consigo dormir. Já li, já escutei música, já fiquei no escuro. Nada. Então resolvi vir para o computador, esperar o sono chegar e enquanto navegava por aí, encontrei este post, do Walter Cruz, falando sobre o exercício Text Munger, postado aqui.

Primeiro, resolvi fazer uma solução “simples”, sem muita sofisticação, lendo os dados de um arquivo de texto para uma unicode string e correndo dois ponteiros sobre esta, indicando o início e o final de cada palavra - basta então chamar a função que “bagunça” os caracteres entre os dois ponteiros.

def MungeWord(word):
  if len(word) = 2:
    return word
  first = word[0]
  last = word[-1]
  middle = list(word[1:-1])
  random.shuffle(middle)
  return ''.join((first, ''.join(middle), last))

def MungeFile(all_data):
  result = []
  index = 0
  while index  len(all_data):
    while index  len(all_data) and not all_data[index].isalpha():
      result.append(all_data[index])
      index += 1
    end = index + 1
    while end  len(all_data) and all_data[end].isalpha():
      end += 1
    result.append(MungeWord(all_data[index:end]))
    index = end
  return result

A segunda idéia é praticamente igual a primeira, mas, ao invés de utilizar dois índices, vou utilizar o método pop das listas para ler os caracteres.

def MungeWord(word):
  if len(word) = 2:
    return word
  word = list(word)
  first = word.pop(0)
  last = word.pop()
  random.shuffle(word)
  return ''.join((first, ''.join(word), last))

def MungeFile(all_data):
  all_data = list(all_data)
  result = []
  if len(all_data) = 2:
    return result
  char = all_data.pop(0)
  while all_data:
    word = []
    while all_data and char.isalpha():
      word.append(char)
      char = all_data.pop(0)
    result.append(MungeWord(''.join(word)))
    while all_data and not char.isalpha():
      result.append(char)
      char = all_data.pop(0)
  return result

A terceira e a quarta idéias já utilizam regular-expressions - como o Walter queria. No entanto, vale ressaltar um detalhe: \w, em Python, considera números e underscores como sendo partes válidas de uma palavra, o que não era desejado no exercício. No entanto, como o próprio Matthew Moss escreveu, muitos escolhem usar \w então consideraremos estas soluções aceitáveis.

A terceira implementação utiliza o conceito de split ou, quebra, da string em diversos elementos de uma lista, de acordo com a expressão regular separadora.

def MungeWord(word):
  if not word or not word[0].isalpha() or len(word) = 2:
    return word
  middle = list(word[1:-1])
  random.shuffle(middle)
  return ''.join((word[0], ''.join(middle), word[-1]))

def MungeFile(all_data):
  regex = re.compile(r"(\W+)", re.UNICODE)
  words = regex.split(all_data)
  result = []
  while words:
    word = words.pop(0)
    result.append(MungeWord(word))
  return result

Já a quarta implementação utiliza o método sub das expressões regulares em Python, para executar uma função de substituição sobre cada uma das ocorrências da expressão em si.

def MungeWord(match):
  word = match.group()
  if len(word) = 2:
    return word
  middle = list(word[1:-1])
  random.shuffle(middle)
  return ''.join((word[0], ''.join(middle), word[-1]))

def MungeFile(all_data):
  regex = re.compile(r"\w+", re.UNICODE)
  all_data = regex.sub(MungeWord, all_data)
  return all_data

Vamos comparar então. Primeiro com um texto pequeno, 1KB:

         226 function calls in 0.003 CPU seconds
   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.001    0.001    0.003    0.003 /home/rodolpho/text_munger.py:19(MungeFile)

         225 function calls in 0.004 CPU seconds
   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.002    0.002    0.004    0.004 /home/rodolpho/text_munger2.py:19(MungeFile)

         424 function calls (418 primitive calls) in 0.003 CPU seconds
   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.001    0.001    0.003    0.003 /home/rodolpho/text_munger3.py:20(MungeFile)

         272 function calls (270 primitive calls) in 0.003 CPU seconds
   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    0.003    0.003 /home/rodolpho/text_munger4.py:19(MungeFile)

Aparentemente, com arquivos pequenos, a diferença em tempo de execução é mínima entre as implementações. Vamos agora jogar um arquivo maior: 3,9MB.

         1389493 function calls in 10.116 CPU seconds
   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    3.990    3.990   10.116   10.116 /home/rodolpho/text_munger.py:19(MungeFile)

         1389492 function calls in 15296.867 CPU seconds
   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1 15269.408 15269.408 15296.867 15296.867 /home/rodolpho/text_munger2.py:19(MungeFile)

         2157415 function calls (2157409 primitive calls) in 1301.620 CPU seconds
   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1 1282.561 1282.561 1301.620 1301.620 /home/rodolpho/text_munger3.py:18(MungeFile)

         1389538 function calls (1389536 primitive calls) in 8.105 CPU seconds
   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    1.530    1.530    8.105    8.105 /home/rodolpho/text_munger4.py:19(MungeFile)

Opa! Agora sim vários resultados interessantes. De cara vemos que solução de usar substitution com expressões regulares apresentou os melhores resultados (oito segundos e pouco, para quase 4MB de texto é um bom resultado). Além disso, vemos que a primeira solução (com os índices) também não ficou tão atrás assim.

A surpresa vem com a segunda idéia: certa de 15297 segundos??? Sim, demorou mais de 4 horas para executar na minha máquina e parece ser uma implementação tão simples, senão mais, que a primeira. Nem tudo que parece simples, é.

A terceira idéia apresentou um resultado tão bom quanto a primeira, o que é uma certa surpresa - eu esperava ver os resultados com regular expressions serem bem melhores do que os demais.

Eu preciso correr para uma consulta médica que tenho e não posso explicar agora os motivos de tais resultados. Prometo que escreverei um post ainda mais longo sobre isso, com gráficos e tudo mais, estudando tanto a função MungeWord como a MungeFile. (Para quem tem muita pressa, uma dica).

Beijos e Abraços! Bom dia!

por rootguy em 03 de July de 2008 às 09:43

July 01, 2008

Ricardo Banffy

June 30, 2008

Elton Luís Minetto

Últimas vagas para curso de Python em Chapecó

Ainda tem algumas vagas para o curso de Python que vou ministrar em Chapecó. O folder do curso

Curso de Python

por elm em 30 de June de 2008 às 18:58

Devlog

Text Munger (ou nem tudo é como deveria ser)

Tudo começou quando eu esbarrei nesse link . O texto contém 15 exercícios de programação, entre eles o que eu me propus a fazer, o text munger.

O exercício consiste no seguinte: dado um texto qualquer, o text munger deve retornar o texto com as palavras desse texto modificadas da seguinte forma: ao invés da palavra original, teremos a primeira letra da palavra original, o resto da palavra (com exceção da última letra) embaralhado seguido da última letra da palavra.

Dentre as várias soluções disponíveis no ruby quiz, a solução em destaque, de Gordon Thiesfeld, usa a expressão regular \b para dividir as palavras. Expressões regulares são iguais em qualquer linguagem, certo? Bom, quase certo. O b funciona da mesma forma no ruby, perl e php, mas funciona de forma diferente no python. Ou não funciona. Na verdade, não sei se é um bug da implementação ou algo assim.

Eu poderia usar outra regex para dividir as palavras e as pontuações, mas já que o fato do \b não funcionar tinha me deixado frustrado com as regex (e eu não queria pensar muito nelas, pra mim o \b deveria funcionar), parti para outra solução. Descobri o shlex, um analisador léxico simples, que para o que eu precisava, funcionava muito bem.

Minha solução para o problema:


import sys
import shlex

from random import shuffle

def munge(text):
    t = shlex.shlex(text, posix=False)
    t.quotes = "'"
    s = [munge_word(word) for word in t]
    print(" ".join(s))

def munge_word(aword):
    s = list(aword)
    first = s.pop(0)
    try:
      last = s.pop()
    except IndexError:
        return aword
    shuffle(s)
    return first + ''.join(s) + last

try:
  s = open(sys.argv[1]).read()
  munge(s)
except IndexError:
  print("Usage: munge.py file")
 

Observe que a solução não está 100% igual a proposta em ruby. Devido a junção em (" ".join(s)), acabam aparecendo uns espaços em branco que não existiam no texto original.
Existe ainda uma solução em smalltalk proposta pelo Rodrigo Cacilhas no kodumaro. E você gosta de exercícios assim? Sabe porque o \b na implementação de regex do python não funciona como eu esperava? (ou serão minhas expectativas que estão erradas?). Os comentários estão aí para vocês!

por Walter Cruz em 30 de June de 2008 às 18:12

Kodumaro

Embaralhando palavras

Squeak Outro dia o Walter estava falando sobre um comportamento irregular da implementação de expressões regulares em Python, especificamente o token \b.

Havia uma brincadeira em Ruby com regex que seleciona cada palavra em uma frase e embaralha a ordem das letras, mantendo a primeira e a última em seus lugares.

Para separar as palavras e os elementos de espaçamento entre elas, usava-se uma regex com \b. Resolvi fazer a brincadeira em Smalltalk, mas descobri que o token também não funciona, portanto precisei fazer uma expressão que representasse cada bloco: ((\w+)|(\W+)).

Para reproduzir essa brincadeira, usando Squeak, primeiro usando o System Browser crie um método shaked na categoria copying da classe String:
shaked
| aux fst i lst temp |

(self size <= 3) ifTrue: [ ↑ self copy ].

fst := (self byteAt: 1) asCharacter asString.
lst := (self byteAt: self size) asCharacter asString.
aux := self copyFrom: 2 to: self size - 1.
temp := Array new: aux size factorial.

i := 0.
aux permutationsDo: [ :s |
i := i + 1.
temp at: i put: (fst, s, lst).
].

↑ temp at: temp size atRandom.


Agora, em um workspace, execute o seguinte código:
| phr |

" Esta é a frase a ser embaralhada "
phr := 'Kodumaro: as sombras da programação'.

Transcript open.
phr regex: '((\w+)|(\W+))' matchesDo: [ :s |
Transcript show: s shaked.
].

Transcript cr.


Selecione tudo (M-a) e execute (M-d).

[]'s
Cacilhas, La Batalema

por La Batalema Pitonisto (noreply@blogger.com) em 30 de June de 2008 às 10:32

June 28, 2008

Pedro Werneck

Pythonologia

E os sites teimam em não funcionar

Recentemente eu comprei um Macbook e passei a ser usuário do Mac OS X. Neste sistema eu tenho acesso a dois browsers extremamente poderosos: o Safari e o Firefox. Ambos em suas últimas versões.

Como uso Linux pro trabalho eu também comprei uma licença do VMWare Fusion (que já valeu cada um dos centavos gastos) onde rodo um Ubuntu Linux e navego com o Firefox.

Isso significa que em meu ambiente tenho à disposição 2 browsers diferentes sendo que um deles roda em 2 sistemas operacionais distintos.

Eu também gastei R$500 com uma licença original do Windows Vista. Em minha opinião esse dinheiro foi perdido porque o sistema é ruim (não porque é o Windows e sim porque é o Vista). Como não uso o Windows pra nada além de eventuais partidas de Counter-Strike (que não podem ser jogadas no VMWare por causa da falta do suporte à aceleração 3D da placa) eu praticamente não inicio ele em minha máquina. Iniciá-lo também é chato e consome muita memória me obrigando quase sempre a ‘desligar’ o Linux.

Em resumo: Iniciar o Windows pra mim é um transtorno.

Nos últimos meses eu tive que interagir via Web com uma grande quantidade de sites governamentais, bancos, empresas de telefonia e até mesmo lojas de e-commerce e me impressionou a quantidade absurdas de sites que ainda teimam em não funcionar com browsers que não sejam o Internet Explorer.

No passado eu entendia essas coisas porque realmente o IE era usado por 99,9% dos clientes na Web mas hoje, apesar de ainda ser uma grande maioria, esse cenário mudou bastante.

Dependendo das estatísticas que se pega na Internet você pode ver que a presença do IE varia entre 74% e 95% e alguns vão se perguntar: o que são 5% dos navegadores? Porque devemos nos preocupar com 5% dos navegadores Firefox/Safari/Opera/…?

Porque numa pesquisa de 2007 o Brasil tinha 15 milhões de pessoas com acesso à Internet e 5% de 15 milhões são 750.000 pessoas! :)

Me explique uma coisa: que tipo de empresa despresaria 750.000 potenciais clientes somente porque a sua equipe técnica não quer investir um tempo testando o site em um browser “alternativo” e eventualmente corrigir problemas?

Os empresários brasileiros desprezam 750.000 potenciais clientes e depois dizem que seus negócios estão afundando por conta dos impostos altos…

Segue abaixo uma lista de sites que não funcionam com browsers não-IE:

  • http://www.vivo.com.br - Simplesmente não é possível “logar” na parte de serviços deles para aquelas tarefinhas ‘triviais’ como ver a fatura do celular e afins.
  • http://www.claro.com.br - É impossível acessar qualquer informação referente à sua conta no site deles. Outras partes estão OK.
  • http://www.saraiva.com.br - Não é possível alterar o seu endereço de entrega.
  • Todos aqueles “Atendimento Online” que tentei usar não funcionaram.
  • … se vocês lembrarem de mais algum coloquem nos comentários…

O site do Banco Itaú funciona perfeitamente bem com meu browser, mas a disponibilidade dos serviços deles é patética. Pelo menos duas vezes por semana eu recebo um “Erro do servidor” ou um “Serviço indisponível” na cara.

Mas cabe acrescentar que uma vez fiz uma reclamação pro Itaú sobre uma parte do site que não estava funcionando no Firefox e algumas horas depois me ligaram pedindo detalhes para providenciar o conserto. E consertaram mesmo. Isso foi Nota 10!

Como vocês puderam ver eu tenho o hábito de ligar reclamando desses problemas e sugerindo o conserto dos mesmos, mas tenho certeza de que eles jogam fora esses conselhos porque “só” 5% dos acessos deles vêm de browsers alternativos.

Aos amigos do Terra… eu ia acrescentar o Terra TV aqui mas ele subitamente funcionou no meu Firefox :)

por Osvaldo Santana em 28 de June de 2008 às 04:16

I Has Arduino!

Hoje de manhã chegou uma encomenda pelo correio que eu estava esperando a muito tempo: meu Arduino :)

Quando eu tinha uns 9/10 anos de idade eu adorava ‘brincar com eletrônica’ com um amigo meu que tinha uma oficina em seu quintal. Todo dia depois da aula a gente jogava Atari na minha casa e depois ia para o “laboratório” dele montar os projetos que saiam nas revistas Experiências e Brincadeiras com Eletrônica Júnior ou na Be-a-Bá da Eletrônica.

Certo dia esse amigo meu me chamou na casa dele porque ele tinha acabado de ganhar um computador. Era um MSX Expert 1.1 da Gradiente completamente sem acessórios. Quando ele ligou o computador e começaram os primeiros acordes do cartucho de demonstração (Ligue-se ao Expert) eu pensei: “É isso o que eu quero pra minha vida”.

Era exatamente um desses

O processo de programação na época era +/- assim:

10 CLS
20 ON ERROR GOTO 70
30 PRINT "DESLIGANDO O ATARI DA TV E LIGANDO O EXPERT"
40 PRINT "COPIANDO PROGRAMA DO LIVRO..."
50 PRINT "EXECUTANDO O PROGRAMA (RUN)"
60 PRINT "PARABENS! DELIGUE O COMPUTADOR E PERCA TUDO"
70 END
80 PRINT "CORRIGE OS ERROS"
90 GOTO 50
RUN

Mas não foi pra falar disso que eu criei esse post. Vamos voltar ao assunto.

Enquanto morava em Recife o Elvis Pfützenreuter me deu alguns componentes eletrônicos que ele tinha comprado para usar em uma maquete de ferromodelismo que ele tinha desistido de continuar. Isso me fez lembrar de como era bom o cheiro de solda e decidi retomar a eletrônica como Hobby.

Ainda estou aprendendo!

Assim como na computação as coisas evoluiram nos últimos anos com a eletrônica também. Então “aquela” eletrônica que eu conhecia onde a gente usava só uns transistores, uns resistores, uns capacitores, etc… se transformou em algo muito parecido com… informática!

“Brincar” com eletrônica nos dias de hoje quase sempre te levará a usar um microcontrolador, ou seja, você terá um chip programável com software para trabalhar.

E é aí que o Arduino entra na história.

O Arduino é um hardware com especificação livre e possui várias implementações diferentes mas todas elas possuem um microcontrolador Atmel instalado. Como o projeto é aberto existem diversas extensões e projetos que usam ele tal no universo do software livre.

A idéia do hardware livre é tão semelhante à do software livre que existem comunidades formadas em torno destes projetos. As idéias se intercalam também. Para ver isso basta olhar para a IDE utilizada para programar o Arduino. Usa o GCC como compilador e a IDE tem uma implementação livre feita em Java.

Se você, como eu, tem interesse nesse universo e quiser adquirir uma placa Arduino pra ‘brincar’ é só fazer uma visita no site da Symphony e comprar um. O modelo que eu tenho aqui é o de 16K:

I Haz Ardooino!

Update: Esqueci de agradecer ao Blog do Jê que é um dos “praticantes de Arduino” no Brasil e notíciou o lançamento da placa pela Symphony (que tornou a compra mais $acessível$)

por Osvaldo Santana em 28 de June de 2008 às 01:12

June 27, 2008

Pedro Werneck

Começando a tapar os buracos...

Já ficou claro que a operação XOR serve apenas para combinação, que apenas usá-lo para combinar texto com chave não é criptografia de fato, é algo trivial de quebrar, apesar de vários fabricantes de software por aí usarem variações disso. O único caso em que é seguro é usando uma chave do mesmo tamanho do texto, e que seja usada apenas uma vez. Um exemplo de um caso de chave única que é usada

por Pedro Werneck (noreply@blogger.com) em 27 de June de 2008 às 23:53

Gustavo Niemeyer

Watch out for list(dict.keys()) in Python 3

As everyone is probably aware by now, in Python 3 dict.keys(), dict.values() and dict.items() will all return iterable views instead of lists. The standard way being suggested to overcome the difference, when the original behavior was actually intended, is to simply use list(dict.keys()). This should be usually fine, but not in all cases.

One of the reasons why someone might actually opt to perform a more expensive copying operation is because, with the pre-3.0 semantics, the keys() method is atomic, in the sense that the whole operation of converting all dictionary keys to a list is done while the global interpreter lock is held. Thus, it’s thread-safe to run dict.keys() with Python 2.X.

The suggested replacement in Python 3, list(dict.keys()), is not. There’s a chance that the interpreter will give another thread a chance to run before or during the iteration of the view, and this will cause an exception if the dictionary is modified at the same time. To fix the problem, either a lock must protect the iteration, or a more expensive operation such as dict.copy().keys() must be used.

The 2to3 tool won’t help you there, unfortunately. So, keep an eye on it!

por Gustavo Niemeyer em 27 de June de 2008 às 21:57

June 26, 2008

Pythonologia

Também vou me alugar com livros…

Já que tá todo mundo se alugando com seus livros lidos e não-lidos eu vou fazer igual. Afinal eu sou compulsivo por comprar e ler livros (muito mais comprar do que ler).

Aí estão alguns dos meus livros lidos & não-lidos
Aí estão alguns dos meus livros lidos e não-lidos.

Não acaba por aí… tem mais esses aqui:

Mais livros lidos & não-lidos
Mais livros lidos & não-lidos.

E por último (no banheiro) o que eu estou lendo:


Na memória do eBook Reader da Sony tem uns 512MB de PDFs.

por Osvaldo Santana em 26 de June de 2008 às 17:17

Leonardo Gregianin

Ajude a sustentar a Wikipédia e outros projetos, sem colocar a mão no bolso, e concorra a um Eee PC!


A Wikipédia pode ser o primeiro exemplo a vir à sua cabeça (ou não!), mas muitos outros projetos fazem parte do dia-a-dia on-line de muitos de nós, mesmo sem que percebamos. Vários deles são economicamente sustentáveis por seus próprios meios, mas outros dependem basicamente dos recursos de seus próprios integrantes, e da ocasional doação do público.

Ajude a sustentar a Wikipédia e outros projetos, sem colocar a mão no bolso, e concorra a um Eee PC!

…e também a pen drives, card drives, camisetas geeks, livros e mais! O BR-Linux e o Efetividade lançaram uma campanha para ajudar a Wikimedia Foundation e outros mantenedores de projetos que usamos no dia-a-dia on-line. Se você puder doar diretamente, ou contribuir de outra forma, são sempre melhores opções. Mas se não puder, veja as regras da promoção e participe - quanto mais divulgação, maior será a doação do BR-Linux e do Efetividade, e você ainda concorre a diversos brindes!

Projetos que podem ser beneficiados além da Wikimedia Foundation: Creative Commons, JQuery, OpenSSH e Python Brasil.

por Leonardo Gregianin em 26 de June de 2008 às 16:28

Pythonologia

Porque a Web 2.0 não engrena no Brasil?

Hoje, durante a minha leitura matinal, eu esbarrei num post que me levou a outro que me levou a outro.

Um resumo muito rápido do conteúdo desses três posts seria: “Porque o Brasil não desenvolve sites Web 2.0? Porque as faculdades não preparam os estudantes.”

Mas eu gostaria de acrescentar algumas coisas a mais nessa equação: “Qualificação”, “Custo” e “Investimento”.

Eu nunca montei uma empresa de tecnologia no Vale do Silício então não tenho uma referência de como as coisas por lá funcionam em detalhes, mas estou no processo de abertura de empresa aqui no Brasil e tenho um projeto “Web” pra ser desenvolvido.

O meu projeto Web 2.0 não tem nada relacionado à mídia (TV, vídeo, som, música) mas para fins de ilustração vou fingir que a minha idéia seria de montar um site de mídia chamado SeuTubo!. Então vamos à história.

Sou um “mico”-empresário brasileiro típico: o que falta de dinheiro sobra de coragem (insanidade?). E vou atrás do que é necessário para desenvolver meu projeto. Até o momento eu só tenho um Plano de Negócios (Business Plan) que venho desenvolvendo a meses e que julgo estar bom.

Vou adiar ao máximo a abertura formal da empresa porque sei que isso gera muito trabalho que eu ainda não preciso ter. Então parto para desenvolver a aplicação. Eu não sou um técnico/programador/sysadmin perfeito mas, também para fins de ilustração, vou ser um super-homem-do-código.

Como as soluções de vídeo na Web já estão razoavelmente ‘comoditizadas’ eu começo a pescar os componentes da solução aqui e ali pra montar meu site… Uma pitada de Python, outra de PHP, uns MySQLs pra alegrar os amigos que trabalham na Sun, um pouquinho de Java pra indexar os dados, … estamos quase lá… falta só o componente central: o player do lado cliente que é feito em Flash.

Ummm… Google: “Free Flash vídeo player download”… nada… busca de outro jeito trocando “Free” por “Open”… nada também… mais procura… acho algumas coisas bem imaturas e que não estão em pleno desenvolvimento… é, não vale a pena arriscar o meu futuro negócio por essa economia. Hora de colocar a mão no bolso (vazio).

Eu não tenho dinheiro pra comprar nada. Então vamos à procura de um investidor… Onde? Cadê os investidores de risco no Brasil? Tem até um portal pra eles feito *pelo governo* mas a coisa não é tão simples assim (e levaria tempo que eu já não tenho tanto).

Bom… vendo meu carro e compro esses componentes de software. Que sorte! Eu tinha um carro pra me desfazer! Meu filho vai pra escola à pé… já tá na hora dele começar a fazer atividades físicas mesmo…

A tal ferramenta sai barato: $1000 (preço hipotético também). Viva o Brasil! O dólar agora tá uma merreca! E ainda sobrou uma grana da venda do carro…

Termino de desenvolver o meu software. Hora de buscar um lugar pra hospedá-lo. Vocês já viram os custos de infraestrutura de rede no Brasil? Como que minha empresa sobreviveria até ter lucro gastando uma fortuna com as Telecoms? Que negócio Web prospera num país que cobra os preços obcenos do Brasil por um link de 1MB?

E minha aplicação de vídeo? Vocês tem uma noção da quantidade de banda que consome? E se o site fizer sucesso… que bom, não? Não! Porque eu iria à falência antes que esse sucesso vire receita porque as belas-Telecoms iriam me estorquir.

Mas… Aí eu vejo que dá pra hospedar o meu negócio em um país cujas empresas e empresários pensam nas pessoas como eu: EUA. Contrato um serviço de “Cloud Computing” onde eu pago preços baixos sob demanda pelo uso de banda. E cruzo os dedos pro dólar não voltar a subir :)

Legal… meu site tá funcionando lá… já dá até pra abrir ele pro público. Mas espere! Agora que eu percebi isso… o visual do meu site está uma tosqueira só! Preciso ‘dar um tapa’ no visual dele e me certificar que ele está usável, afinal, usabilidade e visual são requisitos da Web 2.0, certo?

Vou atrás de empresas de design e usabilidade… Os caras sabem que eles são poucos e vão te cobrar fortunas pela ajuda. Eles estão certos. Lei básica do mercado: muita demanda + pouca oferta = preço alto.

Tento por outra via: achar um cara de design e/ou usabilidade (provavelmente recém-formado) para ser meu sócio (lembre-se que não tenho grana pra pagar salário, logo, todos os meus ‘funcionários’ precisam ser sócios). Eu tento, tento, tento e… lanço o site feio e pouco usável mesmo. Não acho alguém com esse perfil pra me ajudar (e isso já não é ilustração, é real :D).

Legal… o site está em funcionamento e mesmo feio/torto está fazendo sucesso. Já tem até um dinheirinho entrando! Massa! (em dólar… tenho até dó do meu futuro contador) Agora não dá mais pra esperar. Tenho que formalizar a empresa.

Voltando à vida real: de 20 a 30 dias entre o início do processo e a impressão das notas fiscais. Isso porque moro no Paraná (um dos estados onde a abertura de empresas acontece rapidamente).

Agora troquem o “mico”-empresário brasileiro da história acima pelo Chad Hurley e pelo Steve Chen e vejam se foi difícil assim montar o Youtube?

Será que eles morreram nos primeiros meses de funcionamento porque as fornecedoras de links deles os estorquiram? Será que eles tiveram (ou teriam) trabalho pra encontrar um Angel Investor no Vale do Silício para financiá-los no início? Será que ficou caro e/ou foi difícil achar um especialista em design/usabilidade pra fazer o site deles? E formalizar a empresa deles? Levou um mês?

Então é isso. Muito mais do que o problema da péssima formação dos estudantes do Brasil a dificuldade para se montar um site “Web 2.0″ passa por burocracia governamental, dificuldade de financiamento, infra-estrutura cara, entraves alfandegários/tecnológicos (ex. importar equipamentos não lançados no Brasil) e falta de visão empreendedora do brasileiro (brasileiro prefere ser funcionário).

Nesse cenário cheio de “pragas” é difícil de vingar uma lavoura. E quem resolve se aventurar nesse cenário, como eu, é tratado por louco pelos companheiros. E com razão.

por Osvaldo Santana em 26 de June de 2008 às 15:38

June 25, 2008

Devlog

Comparação de versões

Para um software, dizer que a versão 0.2 é maior que a 0.1 é moleza, mas como dizer que a versão 0.2.2 é maior que a 0.2?

Esse é um tipo de comparação que pode ser necessário feita. Talvez você tenha alguma parte do seu código que tenha uma implementação diferente e melhor para acima da versão x. O b2evolution usa isso, por exemplo, para habilitar o modo TRADITIONAL no Mysql quando o debug está ativado apenas a partir do MySQL 5.0.2. E usa também para habililtar alguns espertezas disponíveis apenas no PHP 5.1.

Em Python, a comparação pode ser feita usando o pkg_resources:

>>> from pkg_resources import parse_version
>>>
>>> parse_version("0.10") > parse_version("0.9")
True

>>> True
True
>>> parse_version("0.2.2") > parse_version("0.2")
True

>>> parse_version("0.1.2") > parse_version("0.2")
False

>>> parse_version("0.2.2") > parse_version("0.2")
True
>>>

Em PHP, usa-se a função version_compare

(Dica do pkg_resources retirada de http://lucumr.pocoo.org/cogitations/2008/06/19/%E2%80%A6-and-010-follows-09/)

por Walter Cruz em 25 de June de 2008 às 15:01

Pythonologia

Mais uma campanha…

Se essa moda pega isso aqui vai ter mais propaganda que a revista Playboy :D

Mas dessa vez a campanha pode me render algum prêmio e, caso você também resolva participar, algum prêmio pra você :)

Deixando a brincadeira de lado eu vou aproveitar para dizer para os leitores desse site que o que o Augusto faz ao doar dinheiro para projetos como o Wikipedia é demonstrar o reconhecimento pelo projeto. Não é só uma questão de dinheiro (que é importante e ajuda esses projetos) mas sim uma forma dos responsáveis por tais projetos medirem os resultados dos mesmos.

Comecei esse mês a reservar uma pequena quantia em dinheiro para doar para projetos que me beneficiam de alguma maneira. Desta forma eu escolho um desses projetos e envio uma doação (ainda pequena) para ele. É fácil, não custa muito e deixa os responsáveis por tais projetos muito felizes.

Agora vamos à campanha do Efetividade.net / BR-Linux:

Ajude a sustentar a Wikipédia e outros projetos, sem colocar a mão no bolso, e concorra a um Eee PC!

…e também a pen drives, card drives, camisetas geeks, livros e mais! O BR-Linux e o Efetividade lançaram uma campanha para ajudar a Wikimedia Foundation e outros mantenedores de projetos que usamos no dia-a-dia on-line. Se você puder doar diretamente, ou contribuir de outra forma, são sempre melhores opções. Mas se não puder, veja as regras da promoção e participe - quanto mais divulgação, maior será a doação do BR-Linux e do Efetividade, e você ainda concorre a diversos brindes!

E não se esqueçam de escolher a Associação Python Brasil como uma das beneficiárias da doação. Como membro fundador da APyB eu garanto que lá estão os mais entusiasmados apoiadores da linguagem Python do Brasil e que esse dinheiro será usado em algum projeto interessante.

Que tipo de projeto? Organização da PyConBrasil, financiamento de projetos de tradução, suporte aos sites da comunidade Python e relacionadas no Brasil, ajuda financeira para construção de grupos regionais, financiamento de viagens de instrutores para ministrar cursos de Python, Django, Zope, Plone, … em regiões onde isso é artigo raro, etc.

por Osvaldo Santana em 25 de June de 2008 às 01:52

June 24, 2008

Marco André Lopes Mendes

Ajude a sustentar a Wikipédia e outros projetos, sem colocar a mão no bolso, e concorra a um Eee PC!

Ajude a sustentar a Wikipédia e outros projetos, sem colocar a mão no bolso, e concorra a um Eee PC!


…e também a pen drives, card drives, camisetas geeks, livros e mais! O BR-Linux e o Efetividade lançaram uma campanha para ajudar a Wikimedia Foundation e outros mantenedores de projetos que usamos no dia-a-dia on-line. Se você puder doar diretamente, ou contribuir de outra forma, são sempre melhores opções. Mas se não puder, veja as regras da promoção e participe - quanto mais divulgação, maior será a doação do BR-Linux e do Efetividade, e você ainda concorre a diversos brindes!

por Marco André Lopes Mendes (noreply@blogger.com) em 24 de June de 2008 às 11:48

Ricbit

Como aprender computação

Dia desses o Lameiro me passou uma lista de livros para desenvolvedores, e eu achei a lista bastante curiosa. Se eu fosse criar uma similar, eu não colocaria nenhum dos livros citados naquela lista! Ao invés disso, a minha lista com os top 10 livros de computação seria a abaixo:


1 - Gödel, Escher, Bach (Hofstadter): Eu começaria com o GEB, por dois motivos. O primeiro é que ele é um ótimo reality check: se você não gostar do GEB, então mude de área, porque computação não é a sua praia :) O segundo motivo é que esse livro tem uma excelente introdução à lógica (proposicional e de predicados), que é a ferramenta básica onde você constrói a ciência da computação.

2 - Concrete Mathematics (Knuth): Você não precisa saber matemática para programar, mas se você quiser ser um bom programador, então matemática é essencial. O Concrete tem todo o básico que você precisa pra fazer análises de complexidade computacional, e tudo escrito de maneira extremamente bem-humorada.

3 - Algorithms in C++ (Sedgewick): Se você já sabe lógica e matemática, então agora pode partir pro estudo de algoritmos. O Sedgewick tem todos os algoritmos básicos, e é uma leitura bem leve: se você está começando com algoritmos agora, esse precisa ser o seu primeiro livro. Ele não vai muito fundo em nenhum tópico, mas isso é compensado pela extrema didática nos tópicos. O livro ainda tem código exemplo pra todos os algoritmos, e várias edições, uma pra cada linguagem (eu sei que tem, pelo menos, C, C++, Java e Pascal).

4 - Introduction to Algorithms (Cormen): Os algoritmos que você aprendeu no Sedgewick, você vai estudar em detalhes no Cormen. Esse livro é extremamente formal, e talvez por isso é o livro-texto usado nos cursos de computaçao do MIT. Ele também cobre algoritmos mais avançados, que o Sedgewick apenas cita (por exemplo, Fibonacci Heap)

5 - The Art of Computer Programming (Knuth): O tAoCP está para o Cormen assim como o Cormen está pro Segdewick, aqui você vai dissecar os algoritmos até o último bit deles. Além de ser uma coleção excelente, a encadernação é muito bonita (mas não se engane, ele fica ótimo na prateleira, mas melhor ainda na sua cabeça).

6 - Effective C++ (Meyers): Agora que você sabe os algoritmos, precisa de uma linguagem para programá-los. Pra falar a verdade, a escolha de linguagem nem importa tanto assim, mas se você escolher uma, aprenda-a tão bem quanto possível. Eu escolhi C++, e esse livro do Meyers é o que diferencia as crianças dos adultos (especialmente para aquelas horas quando você cria uma classe sem destrutor virtual e não sabe por que a memória está vazando).

7 - Effective STL (Meyers): Já teve uma época em que eu não gostava de C++, mas isso é porque eu sou velho o suficiente pra ter mexido em C++ antes que os compiladores tivessem templates. Com templates a linguagem fica muito mais atraente, e esse é o livro que vai te ensinar a dominar a STL.

8 - The Practice of Programming (Kernighan, Pike): Se você leu tudo até agora, então você já é um programador muito bom na teoria. Na prática, entretanto, tem um monte de skills que ainda faltam. Nesse livro você aprende sobre as coisas que usualmente não se aprende na escola: debugging, otimização, unit testing, documentação.

9 - Programming Pearls (Bentley): Com os livros lidos até agora, você já deve ser um excelente programador. O passo final é passar de programador para um true hacker, e esse é um passo que não requer só conhecimento, você também precisa de manha, criatividade e insight. Eu não sei se dá pra ensinar essas coisas, mas esse livro certamente é o que chega mais próximo disso.

10 - The Mythical Man-Month (Brooks): Depois de ler todos os livros acima você estará próximo do nirvana, mas pra atingir o zen da programação de verdade, é preciso lembrar que projetos não precisam só de computadores, precisam de pessoas também. O Mythical Man-Month é um livro de gerência de projetos de software escrito em 1975, mas é surpreendente como ele continua atual. A tecnologia avança, mas as pessoas continuam as mesmas :)

É claro que pra manter uma lista com só dez itens, muita coisa boa fica de fora. Mas a lista acima tem um mérito: foi com esses livros que eu aprendi computação de verdade (vale lembrar que eu sou autodidata, minha graduação foi em engenharia elétrica, e eu quase não tive computação em aulas). Se funcionou pra mim, pode ser que funcione pra você também :)

por ricbit (noreply@blogger.com) em 24 de June de 2008 às 09:25

June 22, 2008

Marcos Daniel

Herança - orientação a objetos com python


Atenção: se você ainda não sabe nada sobre orientação a objetos, leia o artigo anterior.

Uma característica legal de programação orientada a objetos é a Herança. Uma classe pode herdar características de outra (superclasse) e incluir suas próprias. A superclasse é mais genérica, a subclasse, que herda da superclasse, é mais especializada.

Usando o exemplo clássico dos livros e tutoriais de programação, imaginemos a superclasse “Animal”; “Mamífero” é uma subclasse de “Animal” e herda suas características. Mas “Mamífero” tem suas próprias características. “Felino” é uma subclasse de “Mamífero”; “Gato” é uma subclasse de “Felino”.

Herdando as características de “felino”, “Gato” herda também as de “Mamífero” e “Animal”. Mas gato mia e arranha o sofá, coisa que nem todo animal faz.

Em Python seria mais ou menos assim:


# definindo a classe Animal:
class Animal:
    def __init__(self):
        # codigo  para o init aqui
    # metodos de Animal aqui

#definindo a classe Mamifero, herdando de Animal
class Mamifero(Animal):
    def __init__(self):

# definindo Felino
class Felino(Mamifero):

# definindo Gato
class Gato(Felino):

No artigo sobre orientação a objetos, nós criamos a classe TiaVelha.

Agora vamos criar uma classe nova. É a Fofoqueira. Uma Fofoqueira é basicamente uma Tia Velha, mas que faz fofocas - nem toda tia velha faz fofocas. A Fofoqueira é especializada no leva-e-traz.

Acho que ficou implícito que, para criar uma Fofoqueira, basta pegar uma Tia Velha e adicionar a ela o leva-e-traz.

Vamos ao código. Se quiser executar o exemplo, primeiro crie uma pasta para nosso exercício. Salve nela o código da TiaVelha, do outro artigo, com o nome tiavelha.py.

Os métodos da Fofoqueira são leva(fofoca) e traz().

O método leva(fofoca) adiciona uma fofoca qualquer ao repertório de fofocas da Fofoqueira. A Fofoqueira não inventa nada; só repassa o que viu ou ouviu.

No método traz(), a fofoqueira solta de uma vez todas as fofocas do seu repertório.


from tiavelha import *
class fofoqueira(TiaVelha):
    def __init__(self,nome,idade):
        TiaVelha.__init__(self,nome, idade)
        self.fofocas=[]

    def leva(self,fofoca):
        self.fofocas.append(fofoca)

    def traz(self):
        for fofoca in self.fofocas:
            print fofoca

Na linha 1 importamos o conteudo do ‘módulo’ tiavelha. A classe TiaVelha agora está disponível no nosso código.

Na linha 2 a classe fofoqueira é definida; TiaVelha entre parêntesis indica que fofoqueira herda de TiaVe