quinta-feira, dezembro 20, 2007

Tela preta na inicialização do Ubuntu Gutsy

Quando instalei meu Ubuntu Gutsy ele tava com um bug meio chato, quando inicializava não aparecia a famosa logo do com a barrinha carregando, mas ficava tela preta por bastante tempo, até aparecer a tela de login. Então eu simplesmente apertava ALT + F1, e ali em modo texto ele inicializava mais rápido.

Mas um dia desses decidi procurar resolver isso, e é realmente bem simples (na verdade o primeiro resultado no google :-) ). Primeiro é preciso editar o arquivo usplash.conf:

sudo gedit /etc/usplash.conf

que provavelmente deve estar assim

# Usplash configuration file
xres=1280
yres=1024

e no meu caso, com tela de 15'4'', eu atualizei pra isso

# Usplash configuration file
xres=1280
yres=800

depois basta atualizar o tema, que é o simbolo do Ubuntu e a barrinha carregando

sudo update-usplash-theme usplash-theme-ubuntu

e pronto!

quarta-feira, dezembro 12, 2007

Renomear arquivos

Surgiu a pouco a necessidade de renomear todas imagens de uma pasta, so adicionar um termo no início do nome. E nada como um script em Python pra facilitar sua vida:

import os

for nome in os.listdir('.'):
novo_nome = 'MEET_' + nome
os.rename(nome, novo_nome)
print 'OK'

quarta-feira, dezembro 05, 2007

Configurando o Gedit

Gosto de usar o Gedit pra programar, inicialmente ele parece ser bem simples, mas pode-se adicionar alguns plugins, basta ir em Edit -> Preferences -> Plugins e escolher. Também tem um pacote no apt-get, o gedit-plugins, que trás alguns adicionais, como auto-completa de chaves, parêntesis, aspas, etc, comentário de um bloco de comandos. Mas aqui tem vários outros bem interessantes, principalmente pra quem programa em Python.

Um bem legal é o Python Outline, que mostra todo o
outline do código no painel lateral. Outro interessante é o Better Python Console, que permite executar o código Python apertando f5, como no IDLE.

Quem é desenvolvedor web, vai gostar do Browser Preview. Tem o Word Completion, que permite auto-completa de palavras que já foram digitadas no documento. O ideal seria ele mostrar os métodos e atributos do objeto, mas esse ainda está na seção de "Requested Plugins", assim como um Debugger pra Python.

É bem fácil instalar novos plugins, normalmente é um arquivo .py e um .gedit-plugin, basta copiá-los para o diretório /usr/lib/gedit-2/plugins e reiniciar o Gedit. Pronto, é so escolher e usar.

UPDATE
Esse artigo tem umas dicas legais também

domingo, dezembro 02, 2007

Enviando e-mails com smtplib

O protocolo SMTP é utilizado para enviar e-emails. E Python possui um módulo embutido, o smtplib, que facilita o envio de e-mails utilizando esse protocolo, e é bem facil de usar:

>>> import smtplib
>>> server = smtplib.SMTP('gmail-smtp-in.l.google.com', 25)
>>> para = 'v2.igor@gmail.com'
>>> de = 'ninguem@nada.com'
>>> msg = '''
... From: ninguem@nada.com
... To: v2.igor@gmail.com
... Subject: Nao eh nada nao
... Aqui eh o corpo da mensagem
... '''
>>> server.sendmail(de, para, msg)
{}
>>> server.close()

A classe SMTP do módulo smtplib serve para se conectar com um servidor de e-mails, caso você tenha um servidor de email rodando localmente, basta usar "localhost". E 25 é a porta padrão do SMTP.

A mensagem de e-mail tem um formato padrão que está definido aqui. Mas os campos mais comuns são:

To: E-mail dos destinatários
Cc: E-mail das pessoas que devem receber uma cópia da menssagem
From: E-mail do criador da mensagem
Subject: Assunto da mensagem
Date: Data e hora em que a mensagem foi enviada

Como se pode perceber, o cabeçalho das mensagens fica no formato Chave: valor... O unico dado que não tem uma chave é o corpo da mensagem em si. A classe Message do módulo email ajuda a formatar essa mensagem:

>>> from email.Message import Message
>>> msg = Message()
>>> msg['Subject'] = 'Assunto do email'
>>> msg.set_payload('Aqui eh o corpo da mensagem')
>>> print msg
From nobody Sun Dec 2 16:29:56 2007
Subject: Assunto do email

Aqui eh o corpo da mensagem


Os valores do cabeçalho podem ser adicionados como na sintaxe de um dicionário do Python, e o método set_payload() serve para adicionar a mensagem.

Ah, e caso no exemplo acima o email não chegue na sua caixa de entrada do gmail, não se esqueça de verificar nos "Spams".

quarta-feira, novembro 28, 2007

Lendo e-mails do Gmail

Estava dando uma olhada no módulo smtplib do Python, então lembrei que li a um tempo atrás sobre um módulo pra ler emails do gmail, é a libgmail.

Tem outro módulo pra isso, é o gmail.py, mas quando eu fui testar recebi um erro de login :/ .

Outro detalhe é que eu baixei o libgmail pelo apt-get, e também tive problemas na hora do login, mas com a ultima versão pelo site do projeto deu certo.

É realmente bem simples de usar:

>>> import libgmail
>>> ac = libgmail.GmailAccount('v2.igor@gmail.com', 'senha')
>>> ac.login()
>>> inbox = ac.getMessagesByLabel('Inbox')
>>> len(inbox)
100
>>> for msg in inbox:
... print msg.subject
...
[ ... ]

Fica ai a dica.

sexta-feira, outubro 19, 2007

Esperando um pouco por uma função

Navegando randomicamente pela web, acabei esbarrando numa classe do módulo threading(pretendo fazer um post sobre Threads breve) que é bem legal. Passamos um tempo para que uma função(callable) seja chamada. Com um exemplo fica mais fácil:

>>> from threading import Timer
>>> def ola():
... print 'ola!'
...
>>> t = Timer(5, ola)
>>> t.start() #espera 5 segundos
>>> ola!

Depois de criado o objeto Timer(), chamamos seu método start() para começar a esperar. Caso precise parar no meio da espera, tem o método cancel(), além de vários outros....

>>> dir(t)
['_Thread__args', '_Thread__block', '_Thread__bootstrap', '_Thread__daemonic', '_Thread__delete', '_Thread__exc_info', '_Thread__initialized', '_Thread__kwargs', '_Thread__name', '_Thread__started', '_Thread__stderr', '_Thread__stop', '_Thread__stopped', '_Thread__target', '_Verbose__verbose', '__class__', '__delattr__', '__dict__', '__doc__', '__getattribute__', '__hash__', '__init__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', '__weakref__', '_note', '_set_daemon', 'args', 'cancel', 'finished', 'function', 'getName', 'interval', 'isAlive', 'isDaemon', 'join', 'kwargs', 'run', 'setDaemon', 'setName', 'start']

Leia mais aqui

quarta-feira, outubro 17, 2007

Esperando o Ubuntu 7.10

A partir de amanhã a nova versão do Ubuntu, o 7.10(Gutsy Gibbon), que trará várias vantagens, estará disponível para download.

Fiz um programinha pra esperar a alteração da página dos downloads...taí pra quem quiser começar a baixar assim que sair(como eu :P)


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

# esperando o lançamento do Ubuntu 7.10 :-)

from urllib import urlretrieve, urlopen
from os import system
from time import sleep
from sys import exit

def save_old():
'''Salva a pagina atual do site de downloads'''
print 'salvando pagina antiga'
urlretrieve('http://br.releases.ubuntu.com/7.10/','UBUNTU.html')
print 'pagina antiga salva'

def espera():
'''Entra na pagina a cada 10 min, e verifica se a pagina mudou'''
try:
old = open('UBUNTU.html').read()
except IOError:
print 'Eh preciso salvar a pagina na primeira vez...'
exit(0)

while True:
print 'vamos verificar'
new = urlopen('http://br.releases.ubuntu.com/7.10/').read()
if new != old:
system('firefox http://br.releases.ubuntu.com/7.10/')
print 'SAIUUUU!!!!'
exit(0)
print 'Ainda nao foi dessa vez...'
sleep(600)


opcao = raw_input('Salvar a pagina atual para comparacao(s/n): ').lower()
if opcao != 's' and opcao != 'n':
print 'Opcao invalida'
exit(0)
if opcao == 's':
save_old()
espera()
else:
espera()

sábado, julho 14, 2007

Mini-Aulas PyGame (parte 1)


Tutorial enviado por Flavio Ribeiro.
Para enviar o seu, mande para o email no perfil ao lado


Olá, hoje vou introduzir poucos conceitos que aprendi pra desenvolver games usando pygame. Vou fazer um pequeno joguinho onde uma nave se move na tela e dá tiros. No fim falo mais sobre esse 'jogo'.

1. Antes de mais nada, instale o pygame. Observe que se você usar alguma distro debian-based, basta um apt-get install python-pygame que ele dá conta do resto. Não sei em outros gerenciadores de pacotes (yum, emerge, etc) mas se não conseguirem usa-los, basta fazer download do tarball.

2. Teste se já tá funcionando importando no interpretador python:

root@nerdy:/# python
Python 2.5.1 (r251:54863, May 2 2007, 16:56:35)
[GCC 4.1.2 (Ubuntu 4.1.2-0ubuntu4)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import pygame
>>>
>
Se o interpretador não chiar, estamos prontos.

3. Vamos agora fazer nosso 'joguinho'. Comece importando os módulos necessários:
import pygame, sys,os
from pygame.locals import *

__obsnãomuitoimportante__: O sys e os vou mostrar porque importei mais na frente, já o pygame.locals eu importei trazendo pro namespace pra economizar digitação.

4. Inicialize o pygame usando o metodo init():

pygame.init()

5. Agora sim, vamos por a mão na massa. Sete o tamanho da telinha do seu jogo e o título (que vai ficar na barrinha):

window = pygame.display.set_mode((200, 200))
pygame.display.set_caption('Meu primeiro jogo!')

6. Sete as váriaveis que vamos usar. Duas que indicarão a posição da nave (x_position e y_position), uma (step) que indica quantos pixels nossa nave vai se mexer quando o usuário apertar pros lados, e outra (shotspeed) que indica a velocidade do tiro.

global x_position, y_position, step
x_position, y_position = 50,100
step = 5
shotspeed = 1

obs_importante: O global indica que modificaremos os valores dessas variáveis dentro de funções. Para saber mais clique aqui.

7. Hora de 'carregar' nossas imagens. Aqui vou carregar o background, a nave e a imagem do tiro ok? Primeiro passo o endereço completo de onde a imagem se encontra (tá aí o os sendo usado!), depois dou um pygame.image.load pra carregar a imagem em uma instância.

background_draw = os.path.join("/home/bioinfo/pygame/mygames","tile3.png")
background = pygame.image.load(background_draw)

ship_draw = os.path.join("/home/bioinfo/pygame/mygames","nave.png")
ship = pygame.image.load(ship_draw)

shot_draw = os.path.join("/home/bioinfo/pygame/mygames","tiro.png")
shot = pygame.image.load(shot_draw)

8. Pra que o background e a nave apareça na tela é necessário que você desenhe (blit) ele. Mas não é só isso, tudo que você for desenhar ou atualizar no pygame você precisa atualizar (flip) a tela. No blit() você passa como argumentos a instância do pygame.image.load e a posição em coordenadas de pixels.

window.blit(background, (0,0)) # Desenha o background na tela. O background tem o mesmo tamanho setado por nós no passo 5)
window.blit(ship, (x_position,y_position)) # Desenha a nave
pygame.display.flip() # Recarrega a janela

9. Pronto, agora o que precisamos é de um laço infinito recebendo todos os eventos do gamer (aperta botão K, aperta botão SPACE, clica com o botão direito do mouse, etc...), e o pygame é bem eficiente nisso. Tudo que você precisa fazer é:

while True:
events = pygame.event.get()

O pygame.event.get() está atribuinto a variavel events uma lista com os eventos que estão acontecendo. Então, quando essa lista não for vazia, alguem apertou ou moveu algo. Vamos tratar esse evento!

for event in events:
if event.type == KEYDOWN and event.key == K_LEFT:
x_position -= step
window.blit(background, (0,0))
window.blit(ship, (x_position,y_position))
pygame.display.flip()

if event.type == KEYDOWN and event.key == K_RIGHT:
x_position += step
window.blit(background, (0,0))
window.blit(ship, (x_position,y_position))
pygame.display.flip()

if event.type == KEYDOWN and event.key == K_SPACE:
shot_pos_x, shot_pos_y = x_position, y_position
while shot_pos_y > 0:
window.blit(background, (0,0))
window.blit(ship, (x_position,y_position))
window.blit(shot, (shot_pos_x,shot_pos_y))
shot_pos_y -= shotspeed
pygame.display.flip()
window.blit(background, (0,0))
window.blit(ship, (x_position,y_position))
pygame.display.flip()

if event.type == QUIT:
sys.exit(0)

Calma, calma. Vou explicar tudinho. Esse for trata os eventos como falei acima, e se o tipo do evento for KEYDOWN (alguem pressionou uma tecla) e essa tecla for setinha-pra-esquerda (K_LEFT) nós alteramos a posição da nave em cinco pixels pra esquerda (diminuimos o x_position com o step), apagamos tudo redesenhando o background por cima de tudo, desenhamos a nave novamente só que no novo lugar e damos um 'refresh' na tela, sacou? O mesmo com o K_RIGHT.

Já com o K_SPACE, que é quando o usuário apertar espaço, nós setamos a posição do tiro que vai partir da nave (ou seja, tem que estar na mesma posição da nave que é x_position e y_position) e fazemos um while dizendo que enquanto a posição do tiro no eixo Y for maior que 0 (ou seja, enquanto o tiro não encostar na aresta superior da tela) o jogo precisa desenhar o background, desenhar a nave, desenhar o tiro e diminuir 1 pixel da posição atual do tiro, que é pra fazer ele subir. Dessa forma, uma hora o tiro vai chegar no topo da tela e sair fora do while. Aí o joguinho redesenha o background e a nave só e dá uma atualizada na tela pra que o tiro suma.

O ultimo evento é só pra o X do canto superior direito da tela funcionar.

Algumas Observações: Existem várias coisas nesse código que precisam ser melhoradas. Esse while do tiro precisa ser refeito porque enquanto o tiro viaja pela telinha nossa nave fica presa, esperando o tiro sumir da tela para que retomemos o controle dela. Isso é um erro.

Outra coisa que preciso aprender é a atualização (flip) da tela. Existe um outro método mais eficiente que é o update(), e usamos ele quando queremos atualizar apenas partes da tela. Essa atualização por partes é chamada de dirty-rect, e ela desenha apenas retângulos de background onde aconteceram movimentos.

No geral é mais ou menos isso. O código completo está aqui e se você quiser ver esse código funcionando pegue as imagens aqui. Não esqueca de modificar o caminho das imagens no comecinho do código. Quando eu for fazendo as otimizações e adicionando funcionalidades ao código vou criando mais tutoriais como esse.

sexta-feira, julho 06, 2007

Python e MySQL

Depois de algum tempo sem postar aqui no blog, vou mostrar um pouco sobre o modulo de Python para acessar um banco de dados MySQL, é o MySQLdb.

No Debian, Ubuntu, etc.... aptitude install python-mysqldb.

Eu presumo que você já saiba algo sobre MySQL, pois não vou falar sobre ele. Bem, depois depois do módulo baixado e instalado, vamos ver se ta funcionando:

>>> import MySQLdb
>>> print MySQLdb.__doc__
MySQLdb - A DB API v2.0 compatible interface to MySQL.

This package is a wrapper around _mysql, which mostly implements the
MySQL C API.

connect() -- connects to server

See the C API specification and the MySQL documentation for more info
on other items.

For information on how MySQLdb handles type conversion, see the
MySQLdb.converters module.

Tudo bem. Para se conectar ao banco é bem simples:

conexao = MySQLdb.connect('host', 'usuario', 'senha', 'banco')

Depois de estabelecida a conexão, é preciso criar um objeto "cursor", é ele quem vai executar os comandos SQL, assim como rebecer os dados que um comando SELECT por exemplo, vou mostrar adiante.
Primeiro vamos criar uma tabela que guarda um nome e um email, será a tabela Dados (o banco deve ser previamente criado):

import MySQLDB

conexao = MySQLdb.connect('host', 'usuario', 'senha', 'banco')
cursor = conexao.cursor()

cursor.execute('''create table Dados (
id int not null auto_increment primary key,
nome varchar(200) not null,
email varchar(100) not null );
''')

cursor.execute('''insert into Dados(nome, email)
values("igor", "igor@v2windcenter.com");
''')
cursor.close()
conexao.close()

O código acima vai criar uma tabela, e adicionar dados nessa tabela. Agora vamos retirar dados do banco, usando o interpretador mesmo:

>>> cursor.execute("SELECT * FROM Dados WHERE nome='igor'")
1L
>>> dados = cursor.fetchall()
>>> print dados
((1L, 'igor', 'igor@v2windcenter.com'),)

o método fetchall() do cursor, retorna todas as linhas que combinam com o SELECT que foi dado acima, observe que é uma tupla de tuplas...

>>> print dados[0][1]
igor
>>> print dados[0][2]
igor@v2windcenter.com

Como no SELECT foi usado *, para selecionar toda a linha, o retorno vai ser uma tupla de linhas que batem com a condição, mas vamos ver como seria para pegar apenas o nome (lembrando que nós temos a tabela dados, quem tem as colunas id, nome e email):

>>> cursor.execute("SELECT email FROM Dados WHERE nome='igor'")
1L
>>> print cursor.fetchone()
('igor@v2windcenter.com',)

o método fetchone() retornou todos os nomes(foi o que procuramos) que combinem com a condição acima. Aqui não é mais uma tupla de tuplas, e sim uma tuplas de valores, pois nós realmente estamos buscando por um unico valor da uma linha.

Bem,

>>> cursor.close()
>>> con.close()

isso é o básico para se inserir e retirar dados de um banco MySQL.
Para algo mais, visite a pagina no projeto:

http://sourceforge.net/projects/mysql-python


quinta-feira, maio 10, 2007

Atributos de classe

Os atributos de classe em Python, são equivalentes às variáveis 'static' de Java. Eles podem ser acessados sem precisar criar uma instância dessa classe, e ficam definidas em todo seu escopo.
Diferente dos atributos de dados, que são as variáveis de instância, e são definidas dentro do método __init__(precedidos por 'self'), os atributos de classe são definidos fora de qualquer método, somente dentro do corpo da classe.

Aqui é um exemplo simples de uma classe com somente um atributo de classe:

>>> class Idade:
... i = 18
...
>>> Idade.i
18

o valor de 'i' pode ser acessada sem precisar criar uma instância da classe Idade. Porém, caso um objeto seja criado, ele também vai poder acessar essa variável:

>>> eu = Idade()
>>> eu.i
18

Assim como 'self' é uma referência a instância atual, também existe uma referência a classe. É um atributo embutido em toda classe: __class__
Vamos usá-lo:

>>> class Idade:
... i = 18
... def __init__(self):
... self.__class__.i += 1
...
>>> Idade.i
18
>>> eu = Idade()
>>> eu.i
19
>>> Idade.i
19

Quando eu acessei Idade.i pela primeira vez, como a classe Idade não havia sido instânciada, o método __init__ não foi chamado. Então o valor de retorno foi 18, o nosso atributo de classe definido acima.
No momento que eu criei o objeto 'eu', o método __init__ foi chamado, e o valor de 'i' foi incrementado, mas perceba o uso de __class__, fazendo referência a classe, assim como 'self' fazendo referência a instância recém criada, no caso, 'eu'. Ou seja, o valor de 'i', apesar de ser incrementado dentro de um método, continua sendo um atributo de classe, e é normalmente acessado por qualquer objeto.

Para quem ainda não se sente muito a vontade com Orientação a Objetos, tem um post anterior que da essa introdução.
No site da nossa comunidade, pythonbrasil.com.br, também tem um boa documentação:
- Introdução OOP
- Módulo B: Python Orientado a Objetos
dentre outros

Assim como no site oficial do Python, python.org:
- Classes (do python tutorial)

Fonte: livro Megulhando no Python

segunda-feira, maio 07, 2007

Nova condicional no Python 2.5

Recentemente instalei o Ubuntu 7.04(Feisty Fawn). Estava usando o 6.10, mas não consegui configurar minha placa Wireless, até desktop 3D tava rodando, com Beryl, mas internet sem fio...nada! Como mesmo no live CD do Feisty Fawn as redes Wireless já apareciam, imediatamente instalei(claro que o problema foi minha "enoorme" habilidade com Linux.. :P). Aliás, tenho um novo problema, agora é com o som(o que está me irritando profundamente), minha placa de som não da sinal de vida! Por favor os gurus em Linux...ajudem!

Mas tive uma boa notícia quando digitei "Python" no terminal: Python 2.5.1c1
Estava adiando minha atualização por mera preguiça.

Uma mudança simples que eu achei bem interessante foi uma nova estrutura para o if:

>>> nome = 'igor'
>>> if nome: print 'tenho nome'
... else: print 'nao tenho nome'
...
tenho nome

Assim é o normal...mas agora pode ser feito assim:

>>> nome = 'igor'
>>> print 'tenho nome' if nome else 'nao tenho nome'
tenho nome

>>> nome = ''
>>> print 'tenho nome' if nome else 'nao tenho nome'
nao tenho nome

Como sempre, as coisas em Python bem mais simples.
Foram adicionadas mais coisas...claro. Essa é só o primeiro link! :)

Veja mais: http://docs.python.org/whatsnew/whatsnew25.html

quarta-feira, abril 11, 2007

Primeira aula de Java

Hoje eu assisti minha primeira aula de Java! Na verdade de Programação Orientada a Objetos, com Java. Eu vejo muitas pessoas na comunidade Python criticar muito a linguagem..."em Python se programa muito mais rápido"..."o código é bem mais limpo e organizado"...etc, etc. So em comparar visualmente os dois códigos, é facil ver que em Python fica realmete bem mais fácil de ler, porém essa é a unica comparação que eu posso fazer, pois nao conheço Java, ainda.

A pouco mais de um ano atrás eu estava no primeiro período do meu curso de Sistemas de Telecomunicações, no CEFET-PB, tendo minha primeira aula de algoritmo, e foi lá realmente onde eu descobri "o que é programação". No mesmo perído foi dado Pascal, onde fiz meus primeiros códigos, gostei, mas ainda sem muita animação. Um amigo da turma, Flávio Ribeiro, já me falava algo sobre Python, mas não dei muita atenção.

No próximo período veio C, já comecei a me interessar mais pelos códigos, achei legal o tratamento quase que direto com a máquina que C proporciona, preocupando-se com cada byte na alocação de variáveis e tal. Nessa época já tinha visto alguns códigos em Python, mas como não ouvia falar muito da linguagem, ainda não dei muita atenção.

Nessa mesma época aconteceu o EPSL - Encontro Potiguar de Software Livre, em Natal-RN. Assisti a palestra sobre TurboGears, com Humberto Diógenes e Jonatas Oliveira, já comecei a olhar Python com outros olhos. E quando Osvaldo Santana aprensentou o 770 e a plataforma Maemo, comecei a ficar fascinado por Python. Teve um minicurso sobre Python, também com o Humberto que foi a gota d'água, não via a hora de chegar em casa e começar a programar em Python!

E aqui estou até hoje. Como no curso de Telecomunicações, aquela cadeira de C seria a ultima de programação, decidi transferi para um curso, tambem no CEFET-PB, totalmente voltado pra desenvolvimento web, Sistemas para Internet, e claro, muito Java.
E como Java só é visto a partir do terceiro período(não consegui dispensar nem C porque a carga horária é maior), decidi começar a assistir aula como ouvinte.

Mas claro que não vou parar de estudar Python, o livro Beginning Python, da Wrox, não sai da minha mesa! A unica diferença é que daqui a um tempo eu vou poder comparar as duas linguagens, sabendo o que estou falando....e acho que já sei qual vou preferir......... :)

terça-feira, abril 10, 2007

Introdução a PyGTK - parte 1

A um tempo venho mechendo bastante em PyGTK, aprendi muita coisa interessante(ainda falta muuito). Apesar de eu estar usando Glade pra "desenhar" minhas interfaces, vou começar falando de "puro" PyGTK.
Dependendo da distribuição de Linux usada, ela já traz o PyGTK instalado, senão você pode encontrar para Linux/Unix e Windows aqui.

Depois de instalado, vamos verificar se tá tudo bem. No interpretador vamos importá-lo:

>>> import pygtk
>>> pygtk.require('2.0')

Não retornando nenhum erro, tá tudo OK. Já existem versões mais novas que a 2.0, a mais atual estável e a 2.10.x.
E importante saber que vamos trabalhar com widgets, um widget é qualquer parte da interface. Um botão é um widget, assim como a janela, uma entrada de texto, etc.
Agora vamos ao código.

class primeiraJanela:
   def __init__(self):
     self.janela = gtk.Window()
     self.janela.set_title('Minha janela')
     self.botao = gtk.Button('Ola Mundo')
     self.janela.add(self.botao)

Aqui nós acabamos de criar uma janela e um botao, colocamos um título na janela e adicionamos o botao nessa janela.
Quando um botão é clicado, o widget emite um sinal. Nós devemos capturar esse sinal e associá-lo a um handler, que nada mais é do que uma função no código, que fará alguma coisa quando receber tal sinal.

     self.botao.connect('clicked', self.botaoClicado)
    self.janela.connect('destroy', self.fecharTudo)

Ao botão, relacionamos o sinal 'clicked' com a função botaoClicado que vamos fazer em seguida. O sinal 'destroy' associando a janela, é quando clicamos no X pra fechá-la. Existem vários tipos de sinais, mas esses servirão por enquanto.
É necessário mostrar cada widget cridado, com o método show(). Basicamente é isso. Criamos o widget, associamos seu sinal com uma função e mostramos ele.
O correto é chamar o método show() tanto para a janela quanto para o botão. Mas tem o show_all(), que mostrará os dois.

     self.janela.show_all()

Pronto. Esse foi o __init__ de nossa classe principal. Agora vamos fazer nossa funções de callbacks, que no caso são somente duas: uma para o botão e uma para fechar a janela

   def botaoClicado(self, button):
     print 'Ola mundo do PyGTK!!' 
  def fecharTudo(self, window):
    self.janela.hide()
    gtk.main_quit()

Quando o botão for clicado, aparecerá no terminal a mensagem: Ola mundo do PyGTK!!
O botao de fechar a janela for clicado, a jenela será escondida, e o programa será fechado.
Aqui termina a nossa classe principal. Agora so falta chamá-la

if __name__ == '__main__':
  primeiraJanela()
  gtk.main()

O código completo está abaixo. Existe muita documentação sobre PyGTK, inclusive no site da nossa comunidade[1]
E claro a documentação oficial[2]


import pygtk
import gtk

class primeiraJanela:
  def __init__(self):
     self.janela = gtk.Window()
     self.janela.set_title('Minha janela')
     self.botao = gtk.Button('Ola mundo!')

     self.janela.add(self.botao)

     self.janela.connect('destroy', self.fechar)
     self.botao.connect('clicked', self.botaoClicado)

     self.janela.show_all()

  def botaoClicado(self, button):
     print 'Ola mundo do PyGTK!'

  def fechar(self, window):
     self.janela.hide()
     gtk.main_quit()

if __name__ == '__main__':
  primeiraJanela()
  gtk.main()

[1]Python Brasil
[2]Tutorial PyGTK

quarta-feira, março 28, 2007

Xrange != Range

Uma das primeiras coisas que a gente aprende quando começa a estudar Python é a função range(). So um simples resumo de como ela funciona:

>>> range(10)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

quando colocamos só um argumento, a contagem começa do zero e vai até o numero dado menos um.
Mas também pode passar o numero inicial:

>>> range(5,10)
[5, 6, 7, 8, 9]

Existe um terceiro argumento, opcional:

>>> range(1,20,3)
[1, 4, 7, 10, 13, 16, 19]

nesse caso, o range ta de um a vinte, pulando de três em três.

Mas qual a diferença entre range e xrange. Aparentemente são a mesma coisa:

>>> for a in range(5):
... print a ,
...
0 1 2 3 4

>>> for a in xrange(5):
... print a ,
...
0 1 2 3 4

Mas eles têm uma diferença. O range gera uma lista, com cada um dos elementos pedidos, so que imagine um range com milhares de números, milhões....isso começaria a ficar lento. É ai que entra o xrange, que é uma classe embutida e cria menos elementos na memória, tornando-se mais rápido.
Mas tem outro detalhe.....o range gera uma lista, e o xrange, um objeto. Mas tudo em Python é objeto! Listas também....
Ai entra outra diferença:

>>> ran = range(10)
>>> dir(ran)
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__', '__doc__', '__eq__', '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__', '__str__', 'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']

se observarmos os métodos da lista gerada pelo range, podemos ver que realmente é uma lista como outra qualquer, tem métodos públicos e privados. Mas olha só:

>>> xran = xrange(10)
>>> dir(xran)
['__class__', '__delattr__', '__doc__', '__getattribute__', '__getitem__', '__hash__', '__init__', '__iter__', '__len__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__setattr__', '__str__']

o objeto gerado pelo xrange só possui métodos privados. O que nos impede de fazer muita coisa.
Mais uma prova de que 'xran' acima não é uma lista:

>>> xran
xrange(10)

Porém podemos acessar algum valor do objeto gerado, como se fosse uma lista ou uma tupla:

>>> xran[3]
3

Como isso é possivel? Bem...podemos ver entre os métodos privados o __getitem__, é ele que é chamado quando procuramos por um elemento dando seu indice entre colchetes.

Na verdade é o seguinte: o range gera uma lista. Xrange é uma classe embutida, logo cria um objeto, que apesar de parecer uma sequência, é diferente, e é o mais aconselhável quando precisarmos gerar uma sequência muuito grande, onde o range se tornaria lento.

Espero ter esclarecido um pouco. Qualquer dúvida ou principalmente complementações e erros, vocês podem e devem comentar! :)


Fonte: livro Beginning Python, Ed. Wrox

sexta-feira, março 16, 2007

De volta do Bossa Conference

Estive no Bossa Conference, em Porto de Galinhas - PE, essa semana. Pra quem não foi, perdeu muita coisa boa.
O congresso foi totalmente voltado pra tecnologia móvel e multimídia, e teve muita coisa interessante. É difícil dizer qual foi a melhor palestra. A plataforma Maemo foi muito citada, assim como Python.

Na maioria dos casos era difícl escolher em qual sala entrar, infelizmente nao assisti as de PyGTK e Hildon, preferi o workshop de PyS60.
É impressionante a facilidade de fazer aplicações pra os smartphones da linha S60 da Nokia, basta instalar o interpretador python no aparelho, escrever o script em python normal(.py) e passar para o celular. Foram criadas algumas bibliotecas específicas, de SMS, camera, etc. E a versão utilizada é o Python 2.2.2. Pretendo começar a fazer alguns programinhas utlizando PyS60, o unico problema que eu achei é que não existe um SDK para Linux, so pra Windows, e como estou usando Fedora e Ubuntu no momento, é preciso rodar o emulador pelo Wine.
Breve eu estarei dando uma introdução da instalção do SDK, e alguns aplicativos simples.

Ainda teve palestras sobre o PyPy, Gstreamer, Canola......muita coisa boa, valeu a pena.

Só tenho duas críticas a fazer: não gostei do fato de não receber nenhum certificado, e achei que o Hotel não é bem preparado para receber esse tipo de evento, as salas são realmente imprenssadas.

Mas acredito que o mais importante nesses eventos e ter a oportunidade de trocas idéias com os convidados, é difícil unir tanta gente boa, e o melhor é que foi a duas horas e meia da minha casa :)

Presença garantida num próximo...espero que aconteça breve.

quinta-feira, fevereiro 22, 2007

Caminho do import

Quando importamos um módulo, como o interpretador Python sabe onde ele está?
Na verdade existe uma lista de locais de onde esses modulos são importados.Para vê-la, basta digitar da linha de comando:

>>> from sys import path
>>> path
['', '/usr/lib/python24.zip', '/usr/lib/python2.4', '/usr/lib/python2.4/plat-linux2', '/usr/lib/python2.4/lib-tk', '/usr/lib/python2.4/lib-dynload', '/usr/local/lib/python2.4/site-packages', '/usr/lib/python2.4/site-packages', '/usr/lib/python2.4/site-packages/HTMLgen', '/usr/lib/python2.4/site-packages/Numeric', '/usr/lib/python2.4/site-packages/PIL', '/usr/lib/python2.4/site-packages/cairo', '/usr/lib/python2.4/site-packages/gst-0.10', '/usr/lib/python2.4/site-packages/gtk-2.0', '/usr/lib/site-python']

E para adicionar um caminho, basta utliziar o método 'append' de lista. Assim podemos adicionar um local para o interpretador buscar os módulos que nós vizemos.

quarta-feira, fevereiro 21, 2007

from 'modulo' import *

Para importar um modulo em Python, basta fazer:

import 'modulo'

isso não e nenhum misterio. Do mesmo jeito que para importar apenas um método ou uma função de um módulo é bem simples:

from 'modulo' import 'algo'

Mas você já deve ter visto o from 'modulo' import *.
Isso importa todu que tem no módulo. Mas ai você se pergunta: e por que não usar somente o import 'modulo' ?
Quando usamos somente o import, todas as funções e atributos desse módulo importado não pertencem ao namespace do nosso modulo, ou seja, caso importamos o módulo 'teste', por exemplo, caso queira me referir a uma função de 'teste' eu terei que fazer:

teste.nome_da_função

já se eu usar o from teste import *, todas as funções e métodos do modulo 'teste' importado serão variaveis locais do meu modulo. E não será mais preciso usar a sintaxe acima.

Um pouco mais de namespaces aqui.

Namespaces, locals() e globals()

Quando nós criamos uma variável, onde ela fica guardada exatamente? Isso vai depender de onde ela foi criada. Caso tenha sido dentro de uma função, ela só existirá para aquela função, será uma variável local, pertencendo a um "namespace" local, e quando essa função não for mais usada, a variavel desaparecerá.

Namespaces são onde ficam registradas as variáveis, e funcionam como um dicionário, onde as chaves são os nomes das variáveis, e os valores são os valores dessas variáveis. Existem três tipos de namespaces:

- Namespace local: como citado acima, se refere a uma função ou método de classe. As variáveis desse namespace só poderão ser acessadas de sua função ou método de classse onde ela pertence.

- Namespace global: é onde ficam todas as variáveis, funções, classes, módulos importados, do módulo corrente. Normalmente esse namespace dura até o fim do programa.

- Namespace embutido: esse é acessível de qualquer módulo, e contém funções e excessões embutidas. Ele é criado quando o interpretador python é aberto, e dura até ele ser fechado. As variaveis desse namespace ficam em um módulo, chamado __builtin__.

Quando, no meio do código, existe uma chamada a uma variável, o interpretador python segue uma sequencia de busca pra achar o valor dessa variável. Primeiro ele procura no namespace local, não achando, procura no namespace global, em seguida no namespace embutido. Caso exista uma função aninhada ou lambda dentro de outra, procura-se primeiro no namespace dessa função, depois no da função ascendente e so depois no global e embutido.

Outra definição interessante é a de escopo. Escopo é uma região textual de um programa em Python, onde um namespace é diretamente acessível. O escopo local de uma função é a região de codigo dela, onde podemos chamar suas variáveis diretamente.

Python tem duas funções muito interessantes, com elas podemos acessar os namespaces em tempo de execução, são elas locals() e globals().

A função locals() retorna um dicionário, onde as chaves são os nomes das variáveis locais, e os valores são os valores dessas varáveis. Vamos ver um exemplo:

def f(n):
....mult = n * 2
....print locals()

Obeserve a função acima f(n), 'n' é o argumento da função, argumentos também pertencem ao namespace local, e dentro da função criamos a variável 'mult'. Agora vamos chamar a função atribuindo um valor para 'n':

>>> f(4)
{'mult': 8, 'n': 4}

Obeserve que locals() retornou o dicionario acima, com as variáveis e seus conteúdos.
O mesmo que locals() faz para um namespace local, globals() faz para o namespace global.

>>> import locais
>>> globals()
{'__builtins__': module '__builtin__' (built-in), '__name__': '__main__', '__doc__': None, 'locais': module 'locais' from 'locais.py'}

Vamos entender o que foi feito acima, direto da linha de comando. Primeiro eu importei o módulo criado acima,chamado de locais.py, que contém o exemplo de locals(). Depois, eu chamei a função globals() e ela me retornou o dicionário acima.
'__builtins__', como eu já citei, é o módulo que contém todas as funções, excessões embutidas, o que forma o namespace embutido.
'__name__' funciona da seguinte maneira. Ao rodar um módulo, ao invés de importá-lo, o valor embutido __name__ será __main__. E como nós estamos da linha de comando, __name__ é __main__
E observe também a presença do módulo que foi importadom 'locais', ao ser importado ele pertence ao namespace global.
'__doc__': None, mostra que nosso módulo corrente não tem nenhuma docstring

Uma utilidade para essas funções é a formatação de string com dicionários, eu falei um pouco disso no post anterior sobre dicionários.

Fonte:
- Livro Mergulhando no Python
- Python tutorial

quarta-feira, fevereiro 07, 2007

Argumentos Opcionais

Python nos permite dar valores padrões para argumentos de funções, assim caso tal argumento não seja definido, será usado seu valor padrão, tornando esse argumento opcional.
Para fazer isso, devemos nomear os argumentos que terão seu valor padrão:

>>> def info(nome, idade=18, curso='python'):

Pronto, a função 'info' acima, possui 3 argumentos, 'nome' é um argumento obrigatório, já 'idade' e 'curso' têm valores padrão '18' e 'python' respectivamente.

>>> info('igor') ## 1
>>> info('igor', 20) ## 2
>>> info('igor', curso='plone') ## 3
>>> info(nome='igor', idade=20) ## 4

Vamos analisar as chamadas acima:

## 1: Nesse caso, entramos somente com o argumento obrigatório, então tando 'idade' quanto 'curso' assumem seus valores padrão, '18' e 'python'

## 2: Agora definimos, além do argumento obrigatório, 'idade', que agora passa a ser '20', e seu valor padrão é ignorado. E 'curso' continua com seu valor padrão.

## 3: Mas e se eu quiser definir o argumeto opcional 'curso' mas usar o valor padrão para 'idade'? Simples. Nesse caso nós, fizemos isso, definimos o argumento obrigatório, e também o argumento opcional 'curso' como 'plone'. Deixando 'idade' com seu valor padrão.

## 4: Esse caso é so para mostrar que os argumentos obrigatórios também poder ser nomeados na hora da atribuição.

terça-feira, fevereiro 06, 2007

Funções lambda

Se você precisa de uma função para fazer algo simples, de apenas uma expressão, existe uma maneira bem prática pra fazer isso em Python, usando uma função lamba.
Elas funcionam como uma função normal, só que possuem uma unica linha.

>>> def f(x):
... return x*2
>>> f(3)
6

usando uma função lambda:

>>> f = lambda x: x*2
>>> f(3)
6

Também podemos usar uma função lambda sem atribuí-la a nenhuma variável

>>> (lambda y: y*3 )(2)
6

As funções lambda são sempre opcionais, tudo que fazemos com ela pode ser feito com uma função normal.

segunda-feira, janeiro 29, 2007

Conhecendo os Dicionários

Hoje vamos dar uma olhada nos dicionarios, um tipo de dados do Python. Vamos começar por sua sintaxe:

d = {'nome' : 'igor', 'idade' : 18, 'curso' : 'python' }

Os dicionarios guardam pares de chave/valor, no caso acima, as chaves sao: 'nome', 'idade' e 'curso'... e elas se referem a seus respectivos valores: 'igor', 18, 'python'.
É importante lembrar que as posições dos pares chave/valor não tem ordem fixa. Os valores podem ser de qualquer tipo, strings, inteiros, tuplas.

Acima criamos o dicionario 'd' da maneira mais clássica, mas existem outras, como a função 'dict':

>>> items = [('nome','igor'), ('idade', 18), ('curso','python')]
>>> d = dict(items)
>>> d
{'idade': 18, 'curso': 'python', 'nome': 'igor'}

Outra maneira interessante de se criar um dicionario, é usando o método 'fromkeys'

>>> dic = {}.fromkeys(['nome','idade'])
{'idade': None, 'nome': None}

Ao invés de None, podemos dar o valor padrão

>>> dic = {}.fromkeys(['nome','idade'],'NADA')
>>> dic
{'idade': 'NADA', 'nome': 'NADA'}

Agora vamos ao que mais interessa, manusear o dicionário...

>>> d['nome']
'igor'

Tem um pequeno problema, e se essa chave nao existisse?

>>> d
{'idade': 18, 'curso': 'python', 'nome': 'igor'}
>>> d['profissao']
Traceback (most recent call last):
File "", line 1, in ?
KeyError: 'profissao'

Pra evitar esse tipo de bug, existe o metodo 'get'

>>> d
{'idade': 18, 'curso': 'python', 'nome': 'igor'}
>>> d.get('nome')
'igor'
>>> print d.get('profissao')
None

Pra alterar o valor de uma chave é muito simples

>>> d['nome']
'igor'
>>> d['nome'] = 'sobreira'
>>> d['nome']
'sobreira'

Observe que eu substitui o valor da chave 'nome', e caso ela ainda não existisse, eu teria acabado de criá-la. Mas que tal verificar se determinada chave existe mesmo?

>>> 'nome' in d
True
>>> 'profissao' in d
False
>>> d.has_key('nome')
True

Pra apagar uma chave também é batante simples:

>>> d
{'curso': 'python', 'nome': 'igor', 'idade': 18}
>>> del d['nome']
>>> d
{'idade': 18, 'curso': 'python'}

Caso você queira ver o que está apagando, ao invés do 'del', pode usar o 'pop'

>>> d
{'idade': 18, 'curso': 'python'}
>>> d.pop('curso')
'python'

Mas eu não quero apagar so uma chave, quero limpar todo o dicionario. Pra isso tem o 'clear'

>>> d = {'nome': 'igor', 'curso': 'python'}
>>> d.clear()
>>> d
{}

Também podemos copiar todo o conteudo do dicionario, para um outro dicionario

>>> d = {'nome': 'igor', 'curso': 'python'}
>>> d2 = d.copy()
>>> d2
{'curso': 'python', 'nome': 'igor'}
>>> d2['curso'] = 'dicionarios'
>>> d2
{'curso': 'dicionarios', 'nome': 'igor'}
>>> d
{'curso': 'python', 'nome': 'igor'}

Observe que uma alteração em um, não altera o conteudo do dicionario copiado

Existe uma utilidade muito legal dos dicioanários, que é formatar string. Aqui vai um exemplo muito interessante

>>> dic = {'nome': 'igor', 'curso': 'python'}
>>> frase = 'meu nome e %(nome)s e estou estudando %(curso)s'
>>> print frase % dic
meu nome e igor e estou estudando python


Bem, espero ter esclarecido um pouco o uso de dicionarios.
Tomei como base o livro Begining Pyhton - From Novice to Professional, de Magnus Lie Hetland
, que eu aconselho muito pra quem ta começando na linguagem.
Até a próxima...

sábado, janeiro 20, 2007

Python Orientado a Objetos

Hoje vai a primeira dica enviada por um visitante do blog, um amigo, Flavio Ribeiro. Foi ele quem me aprensentou a linguagem Python, quando começamos o curso de Sistemas em Telecomunicações no CEFET-PB, e assim como eu, adora a linguagem e quer aprender cada vez mais sobre ela.

Bem, Python é uma linguagem Orientad a Objetos, e aqui Flavio dar uma introdução de como funciona esse tipo de programação:



Python Orientado a Objetos

Olá a todos, hoje vou tentar *introduzir* alguns conceitos de orientação a objetos e creio que isso também me ajudará a tirar algumas dúvidas sobre essa poderosa forma de programação.

A programação orientada a objetos visa prioritariamente o reaproveitamento de código, além de deixar o código mais legivel, elegante e (claro) menor.

Tudo comeca com uma Classe. Ela serve como fábrica de objetos (calma, jájá explico o que é um objeto), e é a base da POO. Tratando isso de uma maneira mais simples, vamos imaginar que você quer criar um joguinho onde terão vários personagens.

class Personagem:
""" Classe que cria personagens do jogo """
def __init__(self,Nome,Poder):
""" Método construtor da classe, onde recebe os parametros Nome e Poder de cada bonequinho """
self.Nome = Nome
self.Poder = Poder
print 'Criando personagem ',Nome,' com poder ',Poder
def Correr(self):
print self.Nome,' está correndo!'
def Chute(self,Adversario):
print self.Nome,' Deu um chute em ',Adversario

Vamos agora explicar: Uma classe chamada Personagem foi criada, e para que ela fabrique algum bonequinho, precisa satisfazer os parametros do método construtor (__init__). A fabricação dele é o que chamamos de objeto ou instância de classe, e agora iremos criar um:

>>> Smurf = Personagem('Papai Smurf',30)
>>> Criando personagem Papai Smurf com poder 30

Viu? Agora temos um objeto chamado Smurf, ou seja, demos vida ao Papai Smurf e ele está pronto pra correr!

>>> Smurf.Correr()
>>> Papai Smurf está correndo!

Agora, para o chute, você deve ter visto que na definição do metodo tem um parametro Adversario, notou? Então teremos que dizer quem vamos chutar!

>>> Smurf.Chute('Gargamel')
>>> Papai Smurf Deu um chute em Gargamel

Deu pra entender como funciona? Da mesma forma que criamos o objeto Smurf, poderemos criar mais inumeros personagens usando apenas essa classe Personagem, usando esses mesmos comandos que digitei acima.

Ainda tem dúvidas não é? O que aquele self representa? O que são aquelas três aspas no inicio dos métodos e da classe? Toda classe precisa de parametros iniciais?

Vamos lá:
O self representa uma váriavel de objeto. Sem o self, quando fossem criados dois ou mais objetos as variaveis iriam sempre ser alteradas e citando como exemplo o código acima, se o ultimo bonequinho chamado 'Tux' fosse criado, todos os outros bonequinhos iam passar a chamar-se Tux também, assim como iam passar a ter o mesmo poder do Tux. Com o self, cada váriavel corresponde ao seu objeto!

As três aspas são chamadas de Doc String. Quando um programa é muito extenso, essas doc strings são de extrema necessidade para que o programador se oriente, elas documentam o código. Olha só como funciona usando o mesmo código acima:

>>> Personagem.__doc__
>>> ' Classe que cria personagens do jogo '

Sacou?

Quanto a ultima pergunta, Não. Não é preciso que toda classe receba dados iniciais, eles podem ser manipulados após a criação dos objetos apenas adicionando metodos de set. Eu poderia criar mais um método ali chamado 'RecebeNome' onde só após a criação do objeto eu iria dar nome a ele.

Bem, pretendo continuar a fazer mini-tutoriais como esse a medida que eu for tomando maior conhecimento da linguagem python. Dessa vez foi apenas um esquente, e espero que tenha ajudado alguem.


segunda-feira, janeiro 15, 2007

Trabalhando com strings

Só pra não deixar o blog parado, vamos dar uma pequena olhada no que o Python pode fazer com strings, apenas alguns métodos. Primeiro vale lembra que em Python, tudo são objetos, então uma string também é um objeto, e tem varios metodos embutidos que facilitam seu manuseio e formatação. Não é preciso declarar variáveis, então para criar uma string, basta atribuir:

>>> nome = 'igor'

>>> nome
'igor'

Ou para tornar um outro tipo em string:

>>> numero = 12.45
>>> string = str(numero)
>>> string
'12.45'

As strings possuem aspas simples ou duplas, para o caso de precisarmos de algumas delas dentro da própria string:

>>> nome = "meu nome é 'igor' "
>>> nome
"meu nome é 'igor' "

E se quisermos escrever uma string usando varias linhas:

>>> nome = ''' estou
... aprendendo
... python'''
>>> nome
'estou\n aprendendo\n python'

Note que um carácter quebra de linha (\n) é adicionado automaticamente com o Enter.
Agora vamos brincar com letras maiúsculas e minúsculas:

>>> nome = 'igor sobreira'
>>> nome.capitalize()
'Igor sobreira'
>>> nome
'igor sobreira'
>>> nome = nome.capitalize()
>>> nome
'Igor sobreira'

capitalize() retorna a primeira letra de string em maiúscula, mas sem alterar o valor da string atual. Tambem tem o upper(), e o lower():

>>> nome = 'igor'
>>> nome = nome.upper()
>>> nome
'IGOR'
>>> nome.lower()
'igor'

Também é possivel procurar por um caracter numa string, mostrando seu índice, mas isso retornara um erro, caso nao encontre:

>>>nome = 'python'
>>> nome.find('t')
2

Outro método muito interessante é o split():

>>> '1+2+3+4+5'.split('+')
['1', '2', '3', '4', '5']

o argumento que splt() recebe, é onde a string será cortada, e retornara uma lista como o exemplo acima.

>>> pasta = '/home/python/programa.py'
>>> pasta = pasta.split('/')
>>> pasta
['', 'home', 'python', 'programa.py']

Agora vamos fazer o inverso:

>>> '/'.join(pasta)
'/home/python/programa.py'
>>> ' ---- '.join(pasta)
'----home----python----programa.py'

Agora o método que eu acho mais interessante de todos é o replace:

>>> nome = 'mergulhando em java'
>>> nome = nome.replace(' em java', ' no python')
>>> nome
'mergulando no python'
>>> nome.replace('mergulhando em ','')
'python'

O replace pode ser utilizado pra tirar aquele estaço que fica no começo ou no final da string, mas, como não é surpresa, o Python ja tem isso pronto, é o strip(), mas ele so tira do começo e/ou do final da string:

>>> nome = ' python e muito bom '
>>> nome.strip()
'python e muito bom'

Ahh..quase ia me esquecendo, concatenar strings! Isso é algo muito dificil, creio que é a maior dificuldade de quem começa na linguagem:

>>> comeco = 'aprendendo '
>>> fim = 'python'
>>> comeco + fim
'aprendendo python'

Bem, e o print de Python, pode ser usado como o 'printf' de C:

>>> print 'aprendendo %s' %'python'
aprendendo python


É claro que existem varios outros métodos para strings, esses são os mais usados, caso alguem lembre-se de outro, pode colocar nos comentários :)

quarta-feira, janeiro 10, 2007

MSN feito em Python

Ja saiu a primeira versão do Emesene, um messenger feito em Python e GTK, que da suporte ao protocolo MSN. Tem uma interface bastante intuitiva, leve e é multiplataforma.

Acabei de testar e gostei muito. Ainda faltam algumas funcionalidades, como transferências de aquivos e mostrar avatar de usuário. Mas uma versão mais completa estará disponivel.

Para fazer o donwload, aqui.

Segue alguns screenshots do Emesene rodando no meu Ubuntu.


Fonte: yguarata.org

Novo Nokia N800


A Nokia lançou seu novo internet tablet, o N800, que veio para susceder o N770. Essa linha de aparelhos é voltada para conexão com a internet, não funciona como celular, ele vem com wi-fi e bluetooth, e suporta aplicações voip. Sua ótima resolução de 800 x 480 é perfeita para visualizar paginas web, tem navegador Opera, plugin de Flash 7, suporte a javascript, etc.

Vem também com webcam VGA, microfone, auto-falantes, saida para fones de ouvido, mini-USB e dois slots SD, um interno e outro externo, que suportam até 2GB cada.

Mas o mais interessante é que o N800 roda em cima de uma plataforma livre, a plataforma Maemo, que é baseada em Linux, o que permite que desenvolvedores Linux portem facilemente suas aplicações.

Mais informações: Pythonologia, Garota sem Fio.

terça-feira, janeiro 09, 2007

Extraindo HTML de uma página

Aproveitando a dica anterior sobre manipulação de arquivos, vou aprensentar uma biblioteca do Python usada pra extrair o codigo HTML de uma pagina web, a urllib.

É bem parecido como a abertura de um aquivo texto, o metodo mais basico é o urlopen:


import urllib
pagina = urllib.urlopen('http://www.v2windcenter.com')
codigo = pagina.read()
pagina.close()
print codigo


Para mais informações sobre o modulo urllib.

Manipulando arquivos

Uma coisa bem interessante em Python é a manipulação de arquivos, que é bastante simples. Vamos tomar como exemplo o arquivo 'texto.txt' :

>>> f = open( '/home/igor/texto.txt', 'w')


a função open possui três argumentos: nome do arquivo, modo e buffer, sendo os dois ultimos opcionais. No exemplo acima, eu usei o nome e o modo 'w'. Vamos falar um pouco sobre os possiveis modos:

Existem três tipos basicos de modos: 'w', 'r', 'a'. Write ('w') é usado para escrever algo no arquivo, apagando o que já havia nele, e caso o arquivo ainda não exista, ele será criado. Mas e se eu quiser apenas adicionar um texto sem apagar o que ja tinha la? Ai estamos falando no modo 'a' (append, pra quem conhece os metodos de listas isso deve ser familiar), agora todo o texto escrito será adicionado no final do que tinha anteriormente (lembrando que o texto inserido é no formato string, não tem nada a ver com listas), nesse caso, se o arquivo também não existir ele será criado sem problemas. E como era de se esperar, 'r' é usado para ler um arquivo já existente.

Mas ainda tem alguns modificadores de modos:

>>> f = open('/home/igor/texto.txt','r+')

quando um '+' é inserido no final de qualquer modo, ele possibilita tanto a leitura quanto a escrita.

>>> f = open('/home/igor/texto.txt','rb')

Esse 'b', adicionado ao lado de algum modo, manuseia o arquivo em binario, e não em texto, como é o padrão.
Caso não seja especificado nenhum modo na função open, sera atribuido 'r' (read), que é o padrão.

O terceiro argumento, também opcional é o buffer, caso seja 0 ou False, não haverá buffer, ou seja, toda vez que o arquivo for ser utilizado, ele será manuseado diretamente do disco rigido; ja se for 1 ou True, então haverá buffer, o arquivo será manuseado da memoria, o que deixa o processo mais rápido. Caso for declarado um numero maior que 1, esse numero indicara o nivel de buffer (em bytes).

Mas agora vamos ao que interessa, escrever:

>>> f = open('/home/igor/Python/texto','w')
>>> f.write('Ola Mundo!')

Como o modo padrão é texto, não é necessário a extensão .txt. Não podemos esquecer de fechar o arquivo:

>>> f.close()

Existem várias maneiras de ler o que está escrito, a basica é read()

>>> f = open('/home/igor/Python/texto', 'r')
>>> ler = f.read()
>>> f.close()
>>> print ler
Ola Mundo!

O metodo read() usado sem nenhum argumento, mostrará tudo que esta no aquivo, mas se quisermos ler apenas os tres primeiros caracters (bytes), podemos usar da seguinte maneira:

>>> f = open('/home/igor/Python/texto') #lembrando que o modo 'r' pode ser excluido pois e o padrao
>>> ler = f.read(3)
>>> print ler
Ola

Aqui apenas especificamos que so serão lidos os tres primeiros caracters (bytes), e caso queira ler o restante, o read() começará de onde parou

>>> restante = f.read()
>>> print restante
Mundo!

Agora vamos adicionar mais alguma coisa no nosso arquivo:

>>> f = open('/home/igor/Python/texto','a')
>>> f.write('\nOla Python')
>>> f.close()

Aqui usamos o 'a' (append), pra adicionar sem apagar o que ja havia no arquivo, e o '\n' é usado pra pular uma linha, lembrando que tudo é string. Agora vamos ver o resultado de outras maneiras:

>>> f = file('/home/igor/Python/texto', 'r')
>>> linha1 = f.readline()
>>> linha2 = f.readline()
>>> f.close()
>>> print linha1
Ola Mundo!

>>> print linha2
Ola Python

O readline() sem argumento, ira ler todo o conteudo de uma linha, porem é possivel dar um limite de caracters, assim como o read. linha1 guarda o conteudo da primeira linha, quando eu chamamos o readline() mais uma vez, ele vai começar a ler de onde tinha parado, ou seja, na segunda linha. Caso não tenha percebido, ao inves de open, usamos file, que da o mesmo resultado.

Pra quem é fã de lista (como eu), não poderia faltar um metodo que retornasse todo o conteudo do arquivo numa lista, e como tudo em Python, ele ja está pronto! É o readlines():

>>> f = open('/home/igor/Python/texto', 'r')
>>> ler = f.readlines()
>>> f.close()
>>> print ler
['Ola Mundo!\n', 'Ola Python']

Cada linha fica em um indice da lista, no formato de uma string.

Para verificar se o arquivo foi realmente fechado, basta digitar:

>>> f.closed
True

Bem...espero ter esclarecido um pouco sobre manipulação de arquivos em Python, alguma duvida, complementação ou correção, podem comentar ou mandar um email.

segunda-feira, janeiro 08, 2007

Primeiro post

Bem, nesse primeiro post, gostaria de dizer o que tenho em mente ao criar este blog. Basicamente pretendo colocar dicas sobre a linguagem de programação Python, tenho muito pouca experiência com programação, então como estou aprendendo Python, tudo que eu for aprendendo e achando interessante na linguagem, vou escrever um pouco, dando dicas.

Desse modo posso compartilhar o que vou aprendendo e principalmente, alguem que esteja lendo e tenha alguma dica a mais, alguma atualização, correção, poderá deixar nos comentarios, ou me mandar um texto completo para ser publicado (igor@v2windcenter.com), afinal a principal meta desse blog é essa, a troca de informações.

Como Python, assim como qualquer linguagem de programação, estão totalmente ligadas com tecnologia, também pretendo falar um pouco sobre novidades tecnológicas que venham a surgir.

Espero ajudar um pouco quem estiver começando no Python, assim como eu, e também receber algumas dicas, pois o principal objetivo desse blog é o aprendizado. :)