domingo, 21 de abril de 2013

Manipulando arquivos XML em Python

Fala pessoal hoje vamos aprender como escrever e ler arquivos XML utilizando a linguagem de programação Python.

Na maioria da vezes temos que salvar informações que os usuários ou sistemas geram. Podemos salvar essas informações de várias formas , seja em um banco de dados, em arquivos de texto, na nuvem, etc. Eu diria que a mais tradicional de todas elas seria salvar em um bom banco de dados como (MySQL, PostgreSQL, Oracle) mas em determinadas aplicações o seu uso é desnecessário ou até mesmo inaplicável. Quando isso ocorre devemos então salvar as informações em arquivos de texto, porém, os arquivos de texto não são lá muito elegantes e legíveis.

Eis então que surge os arquivos XML que podemos definir a grosso modo como sendo arquivos de texto estruturados. O XML é muito utilizado hoje para garantir que dois sistemas possam se interagir normalmente. Um bom exemplo seria o sistema de emissão de nota fiscal online onde a troca de informações entre o sistema proprietário e o sistema da receita federal é toda feita através de arquivos no formato XML.

Escrevendo em formato XML

Para escrever em formato XML utilizando Python podemos utilizar a biblioteca ElementTree que já vem nos pacotes de instalação do interpretador Python.

Para utilizar essa biblioteca primeiramente devemos importa-la :
from xml.etree.ElementTree import Element, ElementTree
Feito isso já podemos utilizar todos os recursos de nossa biblioteca. Todo arquivo XML possui o que podemos chamar de Nó Pai ou simplesmente de root e a partir dele vários desmenbramentos que podem ou não ter filhos e assim sucessivamente. Para criar um root fazemos:
root = Element('Agenda')
Agora a partir do root criamos os sub-nos ou filhos de root:

pessoa = Element('Pessoa') cliente = Element('Cliente', nome='Guilherme', idade='19', peso='71', altura='1.63')
Acima criamos dois filhos de agenda, um chamado pessoa e o outro chamado cliente. Como podemos ver pessoa não possui nenhum atributo enquanto o cliente possui 4 atributos: nome, idade, peso, altura. Quando uma tag não possui atributos dizemos que ela é vazia esse é o caso da tag pessoa.

Ainda temos que dar o comando de escrita, ou seja, o comando que vai criar o nosso arquivo XML. Senão fizermos isso ao final da execução programa não teremos um arquivo gerado. Para gerar/escrever um arquivo XML devemos fazer:

root.append(pessoa) root.append(cliente) ElementTree(root).write('agenda.xml');
Perceba que o comando append foi utilizado em root, isso indica que na estrutura root estamos adicionando duas outras estruturas filhas chamadas sucessivamente de pessoa e cliente. Logo após utilizamos o comando write onde passamos o nome do arquivo que será gerado, caso o arquivo exista o mesmo será atualizado caso contrário um novo arquivo será gerado com o nome que foi passado como argumento.

O nosso arquivo XML tem essa seguinte estrutura:

<Agenda> <Pessoa /> <Cliente altura="1.63" idade="19" nome="Guilherme" peso="71" /> </Agenda>

Lendo arquivos no formato XML

Como já sabemos um arquivo XML tem um Nó (node, raíz). Através desse nó principal podemos descobrir e listar os demais nós presentes em nossa estrutura. Vimos que cada nó contido no root nomeamos de filhos ou sub-nós.

Vejamos como abrir um arquivo XML utilizando o ElementTree:

tree = ElementTree(file='agenda.xml')
Após abrir o arquivo devemos então recuperar o elemento root para então recuperar os seus filhos. Para recuperar o elemento root de um arquivo XML fazemos:
r = tree.getroot()
Agora sabemos que r contém o nó root da nossa árvore XML. Portanto para recuperar os outros nós basta percorrer todos os filhos de root. Para percorrer os filhos de um nó utilizamos:
pessoa = r.find('Pessoa') cliente = r.find('Cliente')
Pronto agora os nós estão armazenados em variáveis possibilitando assim a manipulação. Você pode imprimir tags ou atributos utilizando essa biblioteca, veja como é simples:
print (cliente.tag, cliente.attrib)
Muito simples trabalhar com a linguagem Python não é mesmo? Abaixo segue o código completo para que você possa analisar parte a parte. Um abraço a todos e bons estudos!!! from xml.etree.ElementTree import Element, ElementTree """ Escrevendo os dados em formato XML e gerando o arquivo """ # Criando o nó superior "root" root = Element('Agenda') pessoa = Element('Pessoa') cliente = Element('Cliente', nome='Guilherme', idade='19', peso='71', altura='1.63') root.append(pessoa) root.append(cliente) ElementTree(root).write('agenda.xml'); """ Lendo o arquivo XML que foi persistido pela primeira parte do código """ tree = ElementTree(file='agenda.xml') r = tree.getroot() # Lista os elementos abaixo do root print (r.getchildren()) # Encontra a pessoa pessoa = r.find('Pessoa') # Encontra o cliente cliente = r.find('Cliente') print (cliente.tag, cliente.attrib)

terça-feira, 16 de abril de 2013

Erros comuns que acontecem com iReport




Olá pessoal, hoje vou falar de uma experiência desagradável que tive na minha vida. Vou falar do polêmico iReport. 

O iReport é uma ferramenta para construção de relatórios em vários formatos, tais como: HTML, XLS e PDF. O iReport pode ser utilizado com a linguagem de programação Java ou PHP.

Sem dúvidas o iRepot é uma excelente ferramenta no que se diz respeito à criação de relatórios, porém, seu uso pode acarretar uma experiência não muito agradável. Recentemente utilizei o iReport em um projeto onde tive que criar desde relatórios simples a relatórios mais elaborados. Tive vários probleminhas que tive que descobrir com ajuda de alguns gurus Java e outros que tive que descobrir na raça mesmo.

Por esse motivo fiz um compilado dos problemas que tive na hora de gerar meus relatórios.

  1. Versões diferentes
  2. Fontes diferentes
  3. Gerar .jar 

Versões diferentes

O iReport possui várias versões e nenhuma delas são compatíveis entre si. Se você construir um relatório utilizando a versão 3 e no seu projeto você está utilizando a biblioteca da versão 4 o relatório não irá rodar. O que é no minimo estranho já que sua biblioteca é de uma versão superior a do seu relatório. 

Mas o maior problema não é quando o relatório não roda, o problema começa quando você debuga para achar o erro. Quando você debuga o seu projeto o mesmo diz que não tem nenhum erro e passa normalmente o código, deixando o programador muito confuso já que erros não foram detectados e mesmo assim o seu relatório não abre.

Então se você está desenvolvendo aplicações com iReport e seu relatório não está abrindo fique atento provavelmente a versão do iReport que você incluiu no diretório libs de seu projeto não é a mesma versão do iReport em que o arquivo foi desenhado. 

Fontes diferentes

Parece brincadeira de mal gosto mas é isso mesmo, se seu relatório contem fontes que não estejam instaladas no sistema operacional do cliente ele se quer irá abrir ou muito menos dar uma mensagem de erro. Isso acontece também pelo fato do iReport ser na minha opinião um pouco "ingenuo", ora se a fonte não está instalada no cliente apresente uma fonte padrão da mesma família da fonte não instalada, por exemplo: sans-serif, serif, courier, etc.

Uma dica de quem já quebrou a cabeça com isso. Use somente fontes que você tenha certeza que estejam instaladas no cliente, ou use fontes que sejam genéricas como: sans-serif, serif, etc.

Gerar .jar

Esse é um problema muito frequente em qualquer tipo de aplicação, mas quando você utiliza o iReport ele pode ficar um pouco mais chatinho de resolver. O jar é o executável de um programa Java então todos os arquivos de seu programa estão contidos no jar. Caso você não inclua os arquivos em seu .jar o mesmo não irá executar na máquina cliente ... mesmo se você instalar o iReport na máquina do cliente.

Parece coisa de boçal essa dica mas programadores .NET irão gostar,  pois o Crystal Reports você não libera ele com a aplicação você deve instalá-lo na máquina do cliente.

Bom pessoal por hoje é só e nos vemos no próximo post. Bons estudos!!!

domingo, 14 de abril de 2013

Número arbitrário de argumentos em funções

Fala pessoal, hoje vou mostrar como trabalhar com números de argumentos arbitrários em funções.  Muitas vezes temos que fazer um código onde não sabemos quantos argumentos serão passados quando o código estiver em execução.

Em Python podemos receber tipos arbitrários de funções de duas formas. A primeira seria usando tupla e a segunda usando dicionario.

Relembrando conceitos

Tuplas são listas de dados imutáveis. Quando o programa está em execução não podemos modificar os valores contidos nos índices da tupla, ou seja, se no inicio do programa a posição 1 da tupla armazena o dado 'programado' até o final do programa a posição 1 irá armazenar esse dado.

Dicionários são listas de dados que combinam par de chave valor, ou seja, invés de associarmos indices com dados no dicionário adicionamos chaves com dados. Por exemplo:

programador = 'Guilherme'
(chave)         (dado)

E para recuperarmos o dado devemos informar o nome da chave.

Simples não é mesmo? Bom vamos voltar para a ideia central do post.

Trabalhando com N parâmetros na chamada da função

Bom primeiramente vamos imaginar o seguinte cenário: "Elabore um programa que realize a somatória de N números inteiros e exiba o valor calculado". 

Sabemos que vamos trabalhar com muitos parâmetros, porém, não nos foi informado quantos. Sabemos também que são números inteiros ou seja entre dicionários e tuplas qual devemos escolher? Se você falou tuplas acertou.

Para identificar que um parâmetro é uma tupla basta  adicionar * antes de seu nome. Veja:

def funcao (*args):     pass
Com isso definimos uma tupla com o nome de args. Para chamar essa função basta colocar o seu nome e adicionar os números que deseja somar:

funcao (1,2,3,4,5,6,7,8,9,10)

E para compilar você deve colocar o comando python e logo após o nome do seu arquivo. Veja:

>> python arquivo.py

O que apareceu na sua tela? Exatamente nada rsrsrs!! Calma pequeno gafanhoto isso aconteceu porque não implementamos a somatória dos números. Vamos fazer isso então.

Para percorrer todos os valores de uma tupla podemos usar o comando for, que serve para percorrer um tipo de dado que seja Iterator. E por definição uma tupla é iterável. Para somar todos os dados da tupla devemos fazer:
soma = 0 for nro in args:     soma += nro return soma
Agora podemos chamar a função e imprimir o seu retorno:

print ( funcao(1,2,3,4,5,6,7,8,9,10)) >> 55
Viu como foi simples? Então o que fizemos foi o seguinte. Montamos uma estrutura for e varremos essa estrutura pegando os itens um a um e adicionamos os seus valores na variável local chamada soma. Ao final da função retornamos o valor de soma.
Veja o código completo:

arquivo.py

def funcao(*args): soma = 0 for nro in args: soma += nro return soma print (funcao(1,2,3,4,5,6,7,8,9,10))

Agora vamos trocar de cenário: "Elabora um programa que simule uma agenda telefonica. Onde o usuário deve informar o nome e o número do contato."

Bom acho que isso não podemos resolver com tuplas correto? Bem ainda nos resta o dicionário será que ele pode nos ajudar? Se você respondeu sim ... você acertou!

Para identificar que um parâmetro é um dicionário devemos adicionar ** antes de seu nome. Veja:

def funcao (**kwargs):     pass
Com isso definimos um dicionário com o nome de kwargs. Para chamar essa função basta colocar o seu nome e adicionar os nomes e seus respectivos números (contatos):

funcao(PHP=88888888, Python=77777777, Java=21212121, C=28826718)
Como você já sabe, se executarmos o nosso arquivo nada irá ocorrer pois nada foi implementado não é mesmo? Bom então lets programar pequeno gafanhoto.

Já sabemos que o for consegue percorrer objetos que sejam iteráveis, e adivinha só ... o dicionário é iterável o///. Então o nosso código ficará assim:
arquivo.py
def funcao(**kwargs): print ('Name \t Number ') for contato in kwargs: print ("\n{}\t{}".format(contato, kwargs[contato])) funcao(PHP=88888888, Python=77777777, Java=21212121, C=28826718)
Nossa muito fácil né pessoal nem parece que em poucas linhas de código já montamos uma agenda telefônica '-'. Sério pessoal, podemos pegar esse código e mandar ele salvar em um arquivo .txt e Ulalá teremos uma agenda *-*.

Porém você deve estar muito emocionado agora, sim eu sei que está kkk. Mas e se precisarmos de uma tupla, um dicionário e mais 3 parâmetros em uma mesma função será que isso é possível?

SIM É PLENAMENTE POSSÍVEL =). VEJA:

def funcao (arg1, arg2, arg3, *args, **kwargs):     pass
Cabe aqui uma dica. A tupla deve ficar antes do dicionário e o dicionário deve ser sempre o ultimo argumento.

Pessoal o post terminou :'( ... Bons estudos e até a próxima!!!

terça-feira, 9 de abril de 2013

Trabalhando com vários arquivos *.java

Fala pessoal, hoje vou mostrar como trabalhar com mais de um arquivo (.java) em seus projetos.

Introdução

Quando estamos aprendendo a programar geralmente escrevemos nossos códigos em um único arquivo. Isso é feito para que o aluno não se perca no decorrer de seu aprendizado e trabalhar com um único arquivo é muito mais simples do que trabalhar com vários.
Quando estamos programando no paradigma orientado a objetos muitas vezes (senão sempre) precisamos de mais que um arquivo. Programas grandes costumam possuir vários arquivos onde uma parte do código chama outro parte de código de um arquivo diferente.
Bom visto que para grandes programas temos que usar mais de um arquivo vamos então aprender como programar utilizando mais de um arquivo ... bora lá pé de pano?

Brincando com os arquivos

Vamos imaginar que temos o seguinte problema: Precisamos desenvolver um sistema para uma loja de jóias, essa loja deseja realizar o cadastro de produtos e clientes. Vamos deixar só isso por enquanto pequeno gafanhoto depois retomamos e brincamos mais ;-)

De acordo com o texto acima eu sei que vou ter no mínimo 3 arquivos não é mesmo? O primeiro arquivo seria para escrever código de manipulação de clientes, o segundo de produtos e o terceiro arquivo seria a minha classe principal.

Mais a questão é: "E se eu quiser fazer tudo no mesmo arquivo?". Na tem problema algum em codificar um programa inteiro em um único arquivo, vejamos por exemplo como criar as 3 classes de nosso programa em um único arquivo:


public class TestJoalheria { public static void main() { // CÓDIGO OCULTO } } public class Cliente { // CÓDIGO OCULTO } public class Produto { // CÓDIGO OCULTO }
Esse seria o nosso arquivo único com todas as classes que nosso sistema possui. Veja que não tem problema algum em ter todo o código em um único arquivo. A desvantagem em ter tudo programado em apenas um único arquivo seria a complexidade que o código ganharia. Imagine ter que procurar um erro em um arquivo que tenha 50 classes e o total de linhas seja igual à 100.000 linhas?!

Já que tratar tudo em um arquivo é algo muito complexo, imagine agora se o mesmo programa de 100.000 linhas estivesse divido em 50 arquivos diferentes. É muito mais fácil procurar um erro em um arquivo que você sabe que o erro está ali e esse arquivo tem agora 2000 linhas ... conseguiu enxergar a vantagem pequeno gafanhoto?

Bom vamos ver como ficou o código da Joalheria em vários arquivos? DICA: INCREMENTE FUNCIONALIDADES A MAIS NO SOFTWARE, SEI LÁ CONSTRUA UMA INTERFACE GRÁFICA ... OU DEIXE UM COMENTÁRIO DIZENDO O QUE GOSTARIA QUE EU MODIFICASSE NO CÓDIGO PARA TE AJUDAR MELHOR. BONS ESTUDOS. 

Cliente.java
public class Cliente { private String nome; private int idade; private String endereco; private String telefone; public Cliente(String nome, int idade, String endereco, String telefone) { this.nome = nome; this.idade = idade; this.endereco = endereco; this.telefone = telefone; } public String getNome() { return nome; } public int getIdade() { return idade; } public String getEndereco() { return endereco; } public String getTelefone() { return telefone; } }

Produto.java public class Produto { private String descricao; private float preco; private int estoque; public Produto(String descricao, float preco, int estoque) { this.descricao = descricao; this.preco = preco; this.estoque = estoque; } public String getDescricao() { return descricao; } public float getPreco() { return preco; } public int getEstoque() { return estoque; } }

Joalheria.java import java.util.List; import java.util.ArrayList; public class Joalheria { private List clientesCadastrados; private List produtosCadastrados; public Joalheria() { clientesCadastrados = new ArrayList<>(); produtosCadastrados = new ArrayList<>(); } public boolean adicionarCliente(Cliente cliente) { if (cliente != null) { clientesCadastrados.add(cliente); return true; } return false; } public boolean adicionarProduto(Produto produto) { if (produto != null) { produtosCadastrados.add(produto); return true; } return false; } public List getClientesCadastrados() { return clientesCadastrados; } public List getProdutosCadastrados() { return produtosCadastrados; } public int qtdeClientesCadastrados() { return clientesCadastrados.size(); } public int qtdeProdutosCadastrados() { return produtosCadastrados.size(); } }

TestJoalheria.java import javax.swing.JOptionPane; public class TestaJoalheria { Joalheria joalheria = new Joalheria(); private boolean cadastrarCliente(String nome, int idade, String endereco, String telefone) { return joalheria.adicionarCliente(new Cliente(nome, idade, endereco, telefone)); } private boolean cadastrarProduto(String descricao, float preco, int estoque) { return joalheria.adicionarProduto(new Produto(descricao, preco, estoque)); } private void imprimirClientes() { int qtde = joalheria.qtdeClientesCadastrados(); if (qtde > 0) { System.err.println("Número de clientes cadastrados na base de dados: " + qtde); for (Cliente c : joalheria.getClientesCadastrados()) { System.out.println("Nome: " + c.getNome()); System.out.println("Idade: " + c.getIdade()); System.out.println("Endereço: " + c.getEndereco()); System.out.println("Telefone: " + c.getTelefone()); System.out.println("------------------------------------"); } } else { System.err.println("Nenhum cliente encontrado!"); } } private void imprimirProdutos() { int qtde = joalheria.qtdeProdutosCadastrados(); if (qtde > 0) { System.err.println("Número de produtos cadastrados na base de dados: " + qtde); for (Produto p : joalheria.getProdutosCadastrados()) { System.out.println("Descrição: " + p.getDescricao()); System.out.println("Preço: " + p.getPreco()); System.out.println("Estoque: " + p.getEstoque()); System.out.println("------------------------------------"); } } else { System.err.println("Nenhum produto encontrado!"); } } // Esse cara nada mais é que o método que dá o ponta pé inicial public static void main(String[] args) { int opcao; TestaJoalheria test = new TestaJoalheria(); do { opcao = Integer.parseInt(JOptionPane.showInputDialog("Informe o que deseja cadastrar: \n1-Produtos\n2-Clientes\n\n0-Sair")); if (opcao == 1) { String descricao = JOptionPane.showInputDialog("Entre com a descrição do produto"); float preco = Float.parseFloat(JOptionPane.showInputDialog("Entre com o preço")); int estoque = Integer.parseInt(JOptionPane.showInputDialog("Entre com a quantidade em estoque")); if (!test.cadastrarProduto(descricao, preco, estoque)) { JOptionPane.showMessageDialog(null, "Erro ao cadastrar produto!"); } else { JOptionPane.showMessageDialog(null, "Produto cadasrtrado com sucesso!"); } } else if (opcao == 2) { String nome = JOptionPane.showInputDialog("Entre com o nome"); int idade = Integer.parseInt(JOptionPane.showInputDialog("Entre com a idade")); String endereco = JOptionPane.showInputDialog("Entre com o endereço"); String telefone = JOptionPane.showInputDialog("Entre com o telefone"); if (!test.cadastrarCliente(nome, idade, endereco, telefone)) { JOptionPane.showMessageDialog(null, "Erro ao cadastrar cliente!"); } else { JOptionPane.showMessageDialog(null, "Cliente cadasrtrado com sucesso!"); } } else { JOptionPane.showMessageDialog(null, "Sistema finalizado!!!"); } } while(opcao != 0); test.imprimirProdutos(); test.imprimirClientes(); } }

Novidade!!! Agora vamos ter canal no Youtube =D

Fala pessoal tudo beleza, estou sumido a correria está forte por aqui. Estou querendo dar um start em um projeto antigo que vem desde o temp...