Convertendo um excel xls em table HTML usando python

Posted on 23 \d\e dezembro \d\e 2010. Filed under: computers, python | Tags:, , , , , , , , |

import xlrd
from lxml.html import builder as E, tostring
from lxml.etree import ElementTree

def itermeth(obj, method, endattr):
    for index in xrange(getattr(obj, endattr)):
        yield getattr(obj, method)(index)

def xls_tree(xls_filename, header=True, tableattrs=None):
    if tableattrs is None:
        tableattrs = {}
    workbook = xlrd.open_workbook(xls_filename)
    head = E.HEAD(E.TITLE(xls_filename))
    body = E.BODY()
    for sheet in workbook.sheets():
        if sheet.nrows <= 0 or sheet.ncols <= 0:
            continue # sheet is empty
        table = E.TABLE(E.CAPTION(sheet.name), **tableattrs)
        container = E.THEAD()
        table.append(container)
        cellClass = E.TH
        for xlsrow in itermeth(sheet, 'row', 'nrows'):
            row = E.TR()
            container.append(row)
            if header:
                container = E.TBODY()
                table.append(container)
                cellClass = E.TD
                header = False
            for cell in xlsrow:
                row.append(cellClass(unicode(cell.value)))
        body.append(table)
    return ElementTree(E.HTML(head, body))
    

## Example usage:
html = xls_tree('/home/nosklo/Documentos/teste.xls', 
    tableattrs={'class': 'mytable', 'border': '2'})
# print to screen
print tostring(html, pretty_print=True)
# write to file
html.write('/tmp/resultado.html')
Ler Post Completo | Make a Comment ( 2 so far )

Problema da soma de sub-ítens

Posted on 19 \d\e janeiro \d\e 2010. Filed under: python | Tags:, , , , , , , , , |

Estes dias estava desenvolvendo um programa de conciliação contábil quando me deparei com um problema de programação, no trampo. Passei o programa no canal #python-br e estamos tentando resolvê-lo da forma que tenha mais performance.

Achei muito interessante o fato de conseguir envolver a todos, muita gente está tentando escrever o algoritmo.

O problema consiste em fazer um algoritmo que ao receber uma lista de números inteiros, retorne uma sublista cuja soma é zero.

Porém, tem os seguintes modificadores:

  • Caso não exista nenhuma sublista que alcance zero, a lista vazia deverá ser retornada.
  • Caso exista mais de uma sublista que some zero, o algoritmo deve encontrar aquela que tem o maior valor absoluto, ou seja, o maior valor desconsiderando o sinal (módulo).
  • Em caso de empate, qualquer uma das combinações pode ser retornada.

Nada como alguns exemplos para entender melhor:

  • Para a lista [-5, -3, 10, 16] não tem nenhuma sublista que dê zero, então o algoritmo deve retornar a lista vazia []
  • No caso da lista [-5, -3, 3, 10] o algoritmo deve calcular a sublista [-3, 3] (cuja soma dá 0).
  • Porém, se a lista é [-15, -3, 3, 18] o algortmo tem duas possibilidades cuja soma é zero:
    • retornar [-3, 3] (soma 0)
    • retornar [-15, -3, 18] (soma 0)
  • Quando isso ocorrer, o algoritmo deve estar montado de forma a retornar a sublista com maior valor absoluto, ou seja, [-15, -3, 18] (soma absoluta 36).

Após intensiva pesquisa, encontrei isto na wikipedia. O problema é da classe NP-Hard, e não existe solução linear. Porém com uma linguagem dinâmica, é possível fazer soluções pseudo-polinomiais.

O que estou procurando é justamente este algoritmo otimizado.

Resolvi desenvolver primeiramente o programa de referência. Este programa encontra a solução do problema através da força bruta, ou seja, gera todas as possibilidades de combinações existentes, soma cada uma pra encontrar as combinações cuja soma é zero, e depois verifica qual delas é a que tem maior valor absoluto. A resposta deste código sempre está correta, porém, o tempo para gerar todas as possibilidades é quadrático e dobra a cada novo ítem acrescentado na lista.

Aqui está o programa de referência:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Copyright © 2010 Clóvis Fabrício Costa
# Licensed under GPL version 3.0 or higher 

from itertools import chain, combinations

def acha_combinacao(itens):
    """
    Função que resolve o problema "subset sum" através da geração de todas
    as possibilidades.
    
    Passe uma lista de números inteiros, e a função retornará uma sublista
    cuja soma é zero. 
    
    Caso não exista nenhuma sublista que alcance zero, a lista vazia será
    retornada.
    
    Caso exista mais de uma sublista que tem zero, o algoritmo deve encontrar
    aquela que tem o maior valor absoluto, ou seja, o maior valor 
    desconsiderando o sinal (módulo).
    
    Em caso de empate, qualquer uma das combinações pode ser retornada.
    """
    # gera todas as combinações possíveis
    todas_combs = chain.from_iterable(combinations(itens, n+1)
                                   for n in xrange(len(itens)))
    # procura a maior
    maior_comb = []
    maior_somaabs = 0
    for comb in todas_combs:
        if sum(comb) != 0:
            continue # Combinação não dá zero, pulando.
        somaabs = sum([abs(item) for item in comb])
        if somaabs > maior_somaabs:
            maior_comb = comb
            maior_somaabs = somaabs
    return maior_comb

Para quem quiser tentar fazer o seu algoritmo, estou disponibilizando em meu repositório o programa de referência acima, todas as minhas tentativas até agora, um arquivo de dados contendo números para teste com a respectiva resposta correta, e um programa que lê este arquivo de dados e testa a sua função automaticamente. Desta forma fica fácil achar os problemas do código.

A versão disponibilizada no repositório é compatível com versões do python < 2.6 (o código acima não é).

O repositório está hospedado no bitbucket, e pode ser baixado utilizando o mercurial, com o seguinte comando:

hg clone http://bitbucket.org/nosklo/subset_sum

Para testar seu código, coloque seu arquivo contendo o código na mesma pasta onde você baixou o repositório acima e use o seguinte modelo:

1
2
import referencia
referencia.teste(sua_funcao)

Isso é o suficiente. A sua função será testada com todos os dados de teste que gerei, e vai mostrar qualquer erro encontrado nos resultados.

Qualquer dúvida, estou no canal #python-br da freenode. Muito obrigado a todos que estão ajudando a encontrar este algoritmo.

Ler Post Completo | Make a Comment ( None so far )

Traduzindo pylons book

Posted on 15 \d\e dezembro \d\e 2009. Filed under: python | Tags:, , , , , , , , , |

Iniciando trabalho de tradução do pylonsbook pra Português do Brasil! Alguém pode dar uma força?

O livro está na Gnu FDL. O primeiro passo é arrumar o fonte do livro.

O renatopp já criou um projeto aqui pra gente publicar a tradução.

Ler Post Completo | Make a Comment ( 1 so far )

twisted 9.0 pré

Posted on 24 \d\e novembro \d\e 2009. Filed under: computers, python | Tags:, , , , , , |

Saiu o twisted 9 pre-release!

\o/

Vamos testar enquanto ainda está quente!!

Download aqui.

Ler Post Completo | Make a Comment ( None so far )

Código no escopo global

Posted on 20 \d\e outubro \d\e 2009. Filed under: python | Tags:, , , , |

Todo mundo parece achar que colocar código diretamente no escopo superior (global) de um módulo python é legal. Eu não ligo, só peço que, se você fizer isso, não me faça usar o programa resultante. Mais especificamente, não me faça usar frameworks ou bibliotecas que cheguem a depender deste comportamento.

Afinal, tem um motivo pelo qual todo livro de Python que se preze, no primeiro capítulo, coloca uma cláusula desta forma:

if __name__ == '__main__':
   # do stuff

Isto permite a execução desta parte do módulo como um script, mas impede a execução caso o módulo seja importado por outro módulo. Todo script pode no futuro ser importado por outro módulo, e como o autor do módulo parece não querer que o código dentro do bloco “if” seja executado neste caso, faz sentido colocar tudo que não faz parte da inicialização do próprio módulo dentro de uma cláusula destas.

__name__ é uma variável definida automaticamente pelo interpretador, que recebe o valor '__main__' quando o script atual é o que foi iniciado no interpretador. Para scripts importados, __name__ é o nome de importação do script. Essa diferença permite escrever código que execute condicionado ao módulo ter sido importado ou executado.

Importar um módulo deve fazer no máximo estas coisas:

  • Importar outros módulos ou globais
  • Atribuir valores constantes a variáveis
  • Adicionar novas funções usando a cláusula def
  • Adicionar novas classes usando a cláusula class
  • Fluxo de controle que pode controlar partes condicionais do módulo para tratar erros ou versões específicas de certas plataformas para os casos acima.

Qualquer outro tipo de lógica executada direto no corpo de um módulo python (código que roda automaticamente durante imports) é tratado com suspeita e provavelmente está no lugar errado.

É um absurdo construir um sistema que se inicia ou se configura baseado em efeitos colaterais da importação de módulos. Você perde o controle de quando o código será executado. Ferramentas de inspeção automática de código, geração de documentação e de testes muitas vezes precisam importar o módulo para efetuar suas tarefas, e isto causa efeitos indesejados.

Ler Post Completo | Make a Comment ( None so far )

ajuste a água conforme o foobar

Posted on 3 \d\e março \d\e 2009. Filed under: irc, python | Tags:, , , , |

Geralmente uma simples conversa de IRC gera um projeto. Desta vez foi o meu iconv_codecs, um módulo python para encodificação e decodificação usando os codecs definidos pelo GNU iconv. Leia aqui a conversa na íntegra:

(mais…)

Ler Post Completo | Make a Comment ( 4 so far )

Licenciamento

Posted on 2 \d\e março \d\e 2009. Filed under: irc, licenciamento, python | Tags:, , , , , |

Estava hoje cedo no irc e tive uma conversa interessante sobre licenciamento e ganhar dinheiro com programas python e opensource.
Coloco aqui a conversa na íntegra.

(mais…)

Ler Post Completo | Make a Comment ( 2 so far )

  • Blog Stats

    • 4,093 hits
  • contribua!

Liked it here?
Why not try sites on the blogroll...