Programe Música: Sonic Pi

É, oficialmente, meu novo hobby. Sonic Pi é uma ferramenta para criação de música ao vivo através de programação Ruby.

É divertidíssimo! Olha só, um exemplo do Sonic Pi tocando um Dó-Ré-Mi-Fá:

# Do-Re-Mi-Fa

use_synth :pluck

melody = [ :C, :D, :E, :F, 0, :F, :F, 0,
           :C, :D, :C, :D, 0, :D, :D, 0,
           :C, :G, :F, :E, 0, :E, :E, 0,
           :C, :D, :E, :F, 0, :F, :F, 0 ]

melody.each do |note|
  if note != 0 then
    play note
  end
  sleep 0.3
end

Numa tarde de domingo, escrevi o seguinte programa:

# Cyber Piano Blues #1
# Author: Elcio Ferreira
# https://elcio.com.br/

beat = 0.45

chords = [ chord(:A3, :minor7), chord(:D4, :minor7), chord(:A3, :minor7), chord(:A3, :minor7),
           chord(:D4, :minor7), chord(:D4, :minor7), chord(:A3, :minor7), chord(:A3, :minor7),
           chord(:E4, :minor7), chord(:D4, :minor7), chord(:A3, :minor7), chord(:E4, :major7),
           ]

basses = [ :A2, :C3, :E3, :A2, :D3, :F3, :E3, :C3, :E3, :D3, :C3, :E3,
           :A2, :C3, :A2, :C3, :D3, :F3, :A2, :C3, :E3, :A2, :E3, :A2 ]

melody = [[ :A4, :B4, :C5, :E5, :B4, :C5, :E5, :Fs5, :A4, :B4, :C5, :E5, :B4, :C5, :E5, :Fs5,
            :E5, :B4, :C5, :E5, :B4, :C5, :E5, :C5,  :E5, :B4, :C5, :E5, :B4, :C5, :E5, :C5,
            :C5, :E5, :G5, :E5, :C5, :A4, :F4, :C5,  :C5, :E5, :G5, :E5, :C5, :A4, :F4, :C5,
            :A4, :B4, :C5, :E5, :B4, :C5, :E5, :C5,  :A4, :B4, :C5, :E5, :B4, :C5, :E5, :C5,
            :B4, :G4, :B4, :D5, :F5, :D5, :F5, :D5,  :B4, :G4, :B4, :D5, :F5, :D5, :F5, :D5,
            :B4, :C5, :E5, :Fs5,:E5, :Gs5,:E5, :D5,  :B4, :C5, :E5, :Fs5,:E5, :Gs5,:E5, :D5,
            ],
          [ :B4, :C5, :A4, :E5, :C5, :E5, :B4, :Fs5,
            :B4, :C5, :E5, :E5, :C5, :E5, :B4, :C5,
            :E5, :G5, :C5, :E5, :A4, :F4, :C5, :C5,
            :B4, :C5, :A4, :E5, :C5, :E5, :B4, :C5,
            :G4, :B4, :B4, :D5, :D5, :F5, :F5, :D5,
            :C5, :E5, :B4, :Fs5,:Gs5,:E5, :E5, :D5,
            ]
          ]


live_loop :melody do
  use_synth :piano
  idx = 0
  2.times do |melodyidx|
    4.times do |time|
      if time == 1 or time == 3 then
        melody[melodyidx].each do |tune|
          play tune
          sleep beat * (idx % 2 + 0.5)
          idx+=1
        end
      elsif time == 2 then
        melody[melodyidx].each do |tune|
          2.times do
            play tune
            if idx % 2 == 1 then
              sleep beat * 1
              play tune, pan: 0.5
            end
            sleep beat * 0.5
            play tune, pan: -0.5
            idx+=1
          end
        end
      else
        play :A5
        play_chord chord(:A4, :major7)
        play_chord chord(:A5, :major7)
        sleep beat * 6 * 8
        melody[1].each do |tune|
          play tune
          sleep beat/2
          play tune
          sleep beat/2
        end
      end
    end
  end
end

live_loop :chimes do
  sleep 12 * 4 * 4 * beat
  (12 * 4 * 4).times do
    sample :drum_cymbal_pedal
    sleep beat
  end
end

counter = 0
live_loop :drums do
  if counter % 4 == 0 and counter > 23 and counter < 48 then
    sample :drum_cymbal_open
  end
  sleep beat
  sample :drum_tom_hi_soft, pan: 0.4
  sleep beat * 1.5
  if counter > 23 then
    sample :drum_tom_hi_soft, pan: 0.4
  end
  sleep beat / 2
  if counter > 47 then
    sample :drum_tom_hi_soft, pan: 0.4
  end
  sleep beat
  sample :drum_snare_soft
  if counter % 24 == 0 then
    sample :drum_cymbal_closed, pan: 0.4
  end
  counter += 1
  if counter > 71 then
    counter = 0
  end
end

live_loop :progression_chords do
  use_synth :piano
  4.times do |variation|
    if variation > 0 then
      chords.each do |thechord|
        sleep beat
        play thechord, pan: -0.4
        sleep beat * 4
        play thechord, pan: -0.4
        sleep beat * 3
      end
    else
      chords.each do |thechord|
        sleep beat/2
        play thechord, pan: -0.4
        sleep beat * 2
        play thechord, pan: -0.2
        sleep beat * 1.5
        sleep beat/2
        play thechord, pan: 0
        sleep beat * 2
        play thechord, pan: 0.2
        sleep beat * 1.5
      end
    end
  end
end

live_loop :basses do
  use_synth :piano
  3.times do
    basses.each do |bass|
      2.times do
        play bass, amp: 1, pan: -0.7
        sleep beat/2
        play bass, amp: 1, pan: -0.7
        sleep beat * 3.5
      end
    end
  end
  4.times do
    basses.each do |bass|
      2.times do
        play bass, amp: 1, pan: -0.7
        sleep beat/2
        play bass, amp: 1, pan: -0.7
        sleep beat * 2.5
        play bass, amp: 1, pan: -0.7
        sleep beat
      end
    end
  end
end

live_loop :progression_melody do
  use_synth :piano
  5.times do |round|
    chords.each do |thechord|
      if round == 0 then
        play_pattern_timed thechord, beat/2, amp: 1, pan: 0.7
        sleep beat * 2
        play_pattern_timed thechord, beat/2, amp: 1, pan: 0.7
        sleep beat * 2
      elsif round == 1 then
        play_pattern_timed thechord, beat, amp: 0.6, pan: 0.7
        play_pattern_timed thechord, beat/2, amp: 0.6, pan: 0.7
        sleep beat * 2
      elsif round == 2 then
        play_pattern_timed thechord, beat, amp: 0.6, pan: 0.7
        play_pattern_timed thechord, beat, amp: 0.6, pan: 0.7
      else
        play_pattern_timed thechord, beat/2, amp: 0.6, pan: 0.7
        play_pattern_timed thechord, beat/2, amp: 0.6, pan: 0.7
        sleep beat * 4
      end
    end
  end
end

Se você não estiver afim de instalar o Sonic Pi para testar, e quiser saber como ficou meu blues:

Meu primeiro blues em Sonic Pi

Recomendo! Instala, testa, é divertido!

Otimização de performance prematura: não faça!

Otimização de performance é uma preocupação comum para quem está começando em programação, e muitas vezes mesmo programadores experientes tem dúvidas sobre esse assunto, o que é normal uma vez que o assunto é mesmo complexo. Não vou explicar nesse post tudo o que você precisa saber sobre performance, mas pretendo dizer o mais importante: quando você precisa se preocupar. Isso mesmo, porque um erro muito comum é ver os programadores se preocupar demais com performance, na hora errada.

Então vamos lá: nossos computadores são muito potentes hoje em dia. Muito. Dificilmente mudar a lógica de um cálculo, criar uma variável a menos, otimizar um loop, ou até concatenar menos strings vai fazer algum diferença sensível. Então, não pré-otimize, não otimize antes de medir.

Vamos mostrar um exemplo. Fiz em Python só porque eu gosto, mas a mesma coisa vale para sua linguagem favorita. Escrevi os dois arquivos a seguir:

strings1.py

tamanho=20
a='a'
for i in range(tamanho):
    a*=2
print(len(a))

strings2.py

tamanho=20
a='a' * (2**tamanho)
print(len(a))

São duas maneiras bem diferentes de se criar uma grande string. A segunda é muito mais eficiente que a primeira. Bom, veja os resultados da execução aqui na minha máquina:

$ time python strings1.py
1048576
real 0m0.023s
user 0m0.013s
sys 0m0.008s
$ time python strings2.py
1048576
real 0m0.021s
user 0m0.012s
sys 0m0.008s

Nenhuma diferença prática, certo? Aumentei a variável tamanho para 30, agora notamos diferença:

$ time python strings1.py
1073741824
real 0m1.375s
user 0m0.671s
sys  0m0.691s
$ time python strings2.py
1073741824
real 0m0.586s
user 0m0.235s
sys  0m0.344s

Agora a diferença é absurda, certo? Mas quando foi a última vez que você precisou concatenar strings de um bilhão de caracteres? O caso é: se suas strings vão chegar a esse tamanho, você provavelmente vai saber disso antes. Por exemplo, se você está fazendo um software de tratamento de imagens, parece óbvio que processamento pode ser um problema, certo? Se não, gastar seu tempo e esforço com otimização de performance provavelmente não vale a pena.

Aviso: o código do exemplo 1 é muito ruim, além de dar mais trabalho para escrever. Eu não estou sugerindo que você escreva código ruim de propósito, tá? Apenas que você não se preocupe demais com performance e não gaste seu tempo resolvendo problemas imaginários.

Há, porém, algumas situações em que tudo o que eu disse acima não vale. Nossos processadores são muito rápidos, nossas memórias também. Discos já não são tão rápidos assim. Bancos de dados, mais ou menos. A internet, bom, quem pode confiar na internet, né?

Então, se você vai consumir um webservice, e pode mudar seu algoritmo para fazer dez chamados ao invés de vinte, faça isso. Se vai escrever muito no disco, e puder reduzir em 20% as operações de escrita de arquivos, faça isso. Se escrevendo uma consulta SQL mais complexa você consegue fazer muito menos consultas ao banco de dados e usar mais índices, faça isso.

Eu faço mais ou menos assim em relação a performance:

  1. Vamos usar a internet? Otimize sempre.
  2. Vamos gravar grandes arquivos, ou fazer uso intensivo de disco? Otimize sempre.
  3. Cálculo científico, tratamento de imagens e outras operações de processamento massivo? Otimize sempre.
  4. Bancos de dados com milhões de registros e uso intenso? Otimize sempre.
  5. Uso comum de arquivos e bancos de dados? Cuide de não escrever nada muito ruim, e otimize se der problema.
  6. O resto todo? Escreva pensando em legibilidade, encapsulamento e reuso. Só otimize se tiver problemas.

Publiquei um vídeo sobre isso há um tempo, se você quiser dar uma olhada: Não pré-otimize.

Aprenda os fundamentos: cores no CSS

Quando você se deparar com algum tipo de código, tenha a curiosidade de decifrá-lo.

Me impressiono com a quantidade de programadores que precisam escrever CSS com regularidade e nunca pararam para entender o significado dos código de cores.

É simples: uma cor RGB é composta de três números, representando as cores vermelho (R), verde (G) e azul (B). Cada um desses números pode ir de 0 a 255 (1 byte).

Então o vermelho vivo é:

rgb(255, 0, 0)

Que também pode ser escrito como:

rgb(100%, 0, 0)

Ou, em hexadecimal (255 = FF):

#FF0000

As cores que podem ser “arredondadas” para duplas de letras iguais, como essa, podem também ser escritas assim:

#F00

E é isso. Da próxima vez que você escrever uma cor, vai saber o que significa. Agora pesquisa sobre RGBA, você via ver como fica fácil entender.

Mas não é só sobre cores. Faça isso sempre que se deparar com qualquer tipo de código, tente entender o que ele significa, você vai gastar um pouquinho de tempo no início, mas a vida vai ficar muito mais fácil depois.

Hacker instalou um Backdoor secreto em servidores do Facebook para capturar senhas

Você viu essa notícia?

Hacker Installed a Secret Backdoor On Facebook Server to Steal Passwords

Resumindo, um hacker descobriu um servidor do Facebook (files.fb.com) rodando uma versão desatualizada de um software de compartilhamento de arquivos e conseguiu, através disso, fazer upload de um PHP Web Shell. Ou seja, acesso shell ao servidor.

No post original do cara que descobriu a falha você pode achar uma porção de detalhes técnicos muito interessantes.

O que é esse backdoor secreto?

Backdoor (“porta dos fundos” em inglês) é um software oculto que permite a quem o instalou acesso ao servidor. Um webshell é um backdoor que pode ser acessado em uma interface web. Existem webshells em PHP, ASP, Python, Ruby, C#, Perl e é muito fácil construir um em sua linguagem predileta.

Veja um exemplo de tela de um web shell em PHP:

Webshell em PHP
Webshell em PHP (clique para ampliar)

E seu site, é seguro?

Lição importante que você tirar desse episódio: uma corrente é tão forte quanto seu elo mais fraco. Seu servidor de controle de versão, seu software de gestão de projetos, seu webmail, todas as aplicações web acessórias ao seu site, todos os seus servidores e os computadores da sua equipe precisam estar seguros.

Por exemplo: se seu servidor git tiver o Open SSH desatualizado, se um dos programadores que desenvolve seu site instalar um software malicioso por engano ou se a sua senha do registro de domínios não é forte o suficiente, seu site estará vulnerável, não importa quão bom seja seu código.

Módulo Python: requests

Esqueça urllib e httplib: Requests resolve do jeito certo.

Você pode instalar via pip com:

pip install requests

Depois, veja como é fácil:

>>> import requests
>>> r=requests.get('http://visie.com.br')
>>> for k,v in r.headers.iteritems():print k,'=>',v
... 
content-length => 7669
content-encoding => gzip
accept-ranges => bytes
expires => Mon, 20 Jan 2014 13:18:30 GMT
vary => Accept-Encoding,Cookie
server => Apache
last-modified => Mon, 20 Jan 2014 12:38:24 GMT
cache-control => max-age=3, must-revalidate
date => Mon, 20 Jan 2014 13:18:27 GMT
content-type => text/html; charset=UTF-8
>>> r.status_code
200
>>> r.reason
'OK'
>>> r.content[:15]
'<!DOCTYPE html>'

Se você precisar fazer uma requisição HTTPS com autenticação e obter o retorno em JSON:

>>> r=requests.get('https://httpbin.org/basic-auth/user/passwd',auth=('user','passwd'))
>>> r.json()
{u'authenticated': True, u'user': u'user'}

Para fazer POST:

>>> r=requests.post('https://httpbin.org/post',data={'foo':'bar'})
>>> r.json()['form']
{u'foo': u'bar'}

Tudo muito, muito simples. E o módulo faz muito mais e está muito bem documentado. Olhe lá.

Porque você deveria aprender várias linguagens de programação

tpp_xlargecover
O programador pragmático não está preso a nenhuma tecnologia.

Há um tempo eu li “The Pragmatic Programmer“, uma espécie de livro de auto-ajuda para programadores. Não é um livro técnico, não vai te ensinar técnicas ou tecnologias, mas fala de um jeito de pensar e traz uma coleção de conselhos daquele tipo que parece óbvio mas ninguém nunca faz.

Um desses conselhos era aprender novas linguagens de programação. Os autores recomendam que você se torne proficiente em uma nova linguagem de programação por ano. O que, eu sei, é muito difícil. Eu não tenho conseguido aprender uma nova linguagem por ano. Mas isso não invalida o conselho de que você deve aprender novas linguagens de programação.

Por que aprender linguagens de programação novas?

Cada linguagem de programação traz consigo um jeito de pensar, um conjunto de soluções e uma comunidade com cultura diferente. E isso enriquece você. O bom programador tem uma visão ampla e não está “preso” a uma única tecnologia.

Por exemplo, digamos que você esteja desenvolvendo um sistema em PHP e precise, de tempos em tempos, fazer parsing de feeds RSS cuja URL foi cadastrada pelos usuários. Digamos que você queira fazer o parsing em segundo plano, a cada meia hora. Claro, você pode usar SimplePie, mas ele não é tão “Simple” assim. Dê uma olhada na documentação. SimplePie é muito poderoso, tem uma porção de recursos, mas vai dar algum trabalho para instalar direito, montar seu script, testar e automatizar.

E se você procurar soluções em outras linguagens de programação? Quanto trabalho vai ter? Vamos ver o que Python tem para nós, usando o excelente módulo feedparser. O módulo feedparser está disponível no gerenciador de pacotes do Ubuntu, e também para instalação via PIP.

import feedparser
print feedparser.parse('https://elcio.com.br/feed')

Mais uma meia dúzia de linhas para ler as URLs e salvar os resultados no banco de dados e pronto, temos um arquivo simples com excelente performance para ser colocado no cron. Bom, falando em performance, esse é o típico processamento que vai rodar muito mais rápido se feito em paralelo. Processamento em paralelo com PHP é um parto, certo? Com Python você pode usar o módulo multiprocessing e fazer isso quase que em uma linha só.

Além de ferramentas, linguagens de programação carregam jeitos de pensar

Uma vez que você já tenha resolvido um problema em uma linguagem de programação, você consegue resolver o mesmo problema em qualquer outra, certo? Bom, quando você aprende uma linguagem nova, você acaba tendo que ler um bocado de código de outras pessoas. E isso te ensina novas soluções para os seus velhos problemas.

Isso é diferente de se aprofundar no estudo de sua linguagem atual. O aprofundamento vai fazer você ler mais códigos das mesmas pessoas, da mesma comunidade, da mesma cultura. Aprender uma linguagem nova faz você ler códigos de gente nova, com outra cultura. Na prática, aprender Python vai fazer você melhor programador PHP, aprender Smalltalk vai fazer você melhor programador Java, etc.

Porque Python

De todas as linguagens de programação que você poderia escolher para começar a aprender algo novo hoje, eu recomendo que, se você ainda não sabe Python, comece por ela. Python roda no Google App Engine, no AWS Elastic Beanstalk e é a linguagem de programação por trás da maioria das ferramentas de administração do Ubuntu. Se você quer construir pequenos scripts para automatizar tarefas em seu servidor, ou quer construir grandes aplicações web para rodar em Cloud, ou se quer criar ferramentas de processamento paralelo massivo, ou interfaces gráficas multiplataforma, Python vai servir.

E é, ao mesmo tempo, uma linguagem que possui recurso fantásticos e vai te ensinar coisas incríveis, e uma das linguagens mais fáceis de aprender que eu conheço.

Que tal começar agora? Leia o excelente “Dive Into Python“, faça os exercícios, depois tente desenvolver alguma coisa na linguagem. E veja se você não vai se tornar mais eficiente em sua linguagem atual.

“Jabá”: Python é a linguagem que escolhemos para a aula de integração multi-linguagem do DevOps Heroes, treinamento da Visie que acontece a partir do dia 27 em São Paulo. Quem estiver lá vai ver isso tudo funcionando na prática. As vagas estão se esgotando.

Pare de usar FTP

Há mais de dez anos que meus processos de deploy, isto é, colocar um site ou sistema em produção, não usam FTP. Qualquer bom provedor, nacional ou internacional, oferece ferramentas muito mais eficientes para o deploy de sites e sistemas. E isso inclui desde pequenos sites em WordPress ou HTML estático até portais com milhares de acesso por hora e grandes sistemas rodando em estruturas de cloud computing elástico.

Por que você não deveria usar FTP

FTP é um protocolo muito simples de troca de arquivos, que pode ser útil para uma porção de coisas. Mas não possui os recursos necessários para o deploy e controle eficiente de aplicações web. Entre os problemas com o protocolo FTP, podemos citar:

  1. Falta de integração com controle de versão: você está fazendo uma manutenção num site, cujo diretório tem 5MB de dados. Você alterou não mais que uma dúzia de arquivos, em pastas diferentes. Arquivos texto cujos tamanhos, somados, não passam de 200KB. Como você faz o deploy por FTP? Ou sobe o site todo, “por via das dúvidas”, ou precisa pinçar os arquivos que precisa subir, um a um, certo? Algumas ferramentas de transferência, como o Filezilla, conseguem “sincronizar” as pastas, mas eles fazem isso varrendo as pastas uma por uma e comparando as datas e tamanhos dos arquivos. Leva um tempão e, se algum outro programador alterou os arquivos antes de você isso certamente vai dar problemas. O que nos leva a um segundo ponto:
  2. Falta de recursos de “auditoria” e controle de deploys: não há como obter um log ou lista de quem fez deploy, quando e o que foi feito. Um problema recorrente em ambientes em que uma equipe trabalha com FTP é a sobrescrita de alterações já publicadas. Na pior das hipóteses, gerando perda de trabalho. Mas mesmo que a equipe tenha um ambiente interno de controle de versões e a sobrescrita no FTP seja fácil de resolver, pense na dor de cabeça de ter que explicar para o cliente que o defeito que foi corrigido ontem voltou ao ar hoje, mas já estamos resolvendo.
  3. Falta de automatização: deploy por FTP é feito à mão. Um homo sapiens navega nas pastas de seu computador e do servidor e arrasta o que deve ser atualizado de um lado para outro. Num processo chato e delicado. Se ele arrasta as coisas para a pasta errada, pode ser muito difícil consertar o problema. Pode ser difícil até entender o problema. E se você coloca um homo sapiens para repetir uma mesma tarefa vinte ou trinta vezes, ele certamente vai errar alguma.
  4. Falta de recursos para rollback automatizado: você subiu a alteração. Em seguida abriu o site e viu um “erro de conexão ao banco de dados”. Percebe então que subiu a versão errada, ou no lugar errado. Como voltar atrás? Voltar atrás com FTP é um processo ainda mais manual e trabalhoso do que subir o site. Já vi casos, e não foram poucos, em que foi preciso pedir ao provedor para restaurar o backup diário. E esperar por isso, claro.

O que você deveria usar então?

SSH e Git. Há uma série de ferramentas para deploy automático, como o Capistrano ou o Jenkins. Esqueça isso tudo no começo. Aprenda SSH e Git, e construa seu processo de deploy com isso. Você vai ganhar:

  1. Deploy realmente automático. Com um único comando.
  2. Integração real com o controle de versão. Isso significa que sempre será possível rastrear cada alteração. Também significa rollback automático, o que é maravilhoso.
  3. Controle simplificado de múltiplos ambientes. Precisa fazer deploy em um ambiente de homologação, para mostrar as novidades ao cliente? Um comando. Ele aprovou as novidades, e agora é hora de fazer deploy em produção da versão que foi homologada ontem? Um comando.
  4. Preparação para o futuro. O site cresceu e você precisa agora migrar para um serviço como o AWS Elastic Beanstalk, que oferece escalabilidade “elástica” sob demanda dentro da estrutura de serviços da Amazon. O processo vai ser praticamente indolor. O cliente precisa agora de deploys com zero de indisponibilidade, e você resolveu usar a estratégia Blue Green. Já tem tudo o que precisa.

Por isso, não se conforme em usar FTP. Se precisa estudar SSH e Git, estude, vai valer a pena. Se já sabe, está esperando o quê?

“Jabá”: uma boa maneira de aprender como mudar seus processos de deploy, e muito mais, é o treinamento DevOps Heroes da Visie, que acontece daqui a duas semanas.

 

Artigo recomendado: Two Things About Conditionals in JavaScript

Detalhezinho sobre a linguagem que vale a pena conhecer, e uma boa dica de lógica sobre um erro muito cometido por iniciantes:

“We shouldn’t be fearful of writing about what we know. Even if you write from the most basic point of view, about something which has been ‘around for ages’, you’ll likely be saying something new to someone. That’s because there is no else if in JavaScript.”

Papo de Maluco

Hoje estava brincando com Requests e tive essa ideia maluca:

import requests
import re

def Ed(text):
params=dict(server=’0.0.0.0:8085′,charset_post=’utf-8′,
charset=’utf-8′,pure=1,js=0,tst=1,msg=text)
return re.sub(‘<[^>]*>’,”,re.sub(r’\n+$’,”,
requests.get(‘http://www.ed.conpet.gov.br/mod_perl/bot_gateway.cgi’,
params=params).text))

def SeteZoom(text):
params=dict(server=’127.0.0.1:8088′,pure=1,js=0,tst=1,msg=text)
return re.sub(r’\n+$’,”,
requests.get(‘http://bot.insite.com.br/cgi-bin/bot_gateway.cgi’,
params=params).text)

msg=’Oi!’
while True:
print ‘SeteZoom: %s’ % msg
msg=Ed(msg)
print ‘Ed: %s’ % msg
msg=SeteZoom(msg)

Teste aí, o resultado às vezes é mais inteligente que muito chat entre seres humanos por aí…

Pequena dica de Python: módulo webbrowser

O módulo webbrowser permite abrir uma URL no navegador do usuário. Só isso, simples assim. Por exemplo:

import webbrowser
webbrowser.open("http://visie.com.br")

E o site da Visie será aberto no navegador do usuário. Muito útil se você está fazendo um programa para desktop ou mesmo um script para o terminal. No caso de scripts para terminal, se o usuário estiver rodando o script sob uma interface gráfica o site será aberto no navegador padrão dele, já se estiver rodando via ssh ou num outro terminal sem interface gráfica, será usado um navegador de CLI (como o Lynx) se estiver disponível.

Cowsay: a vaquinha falante do Linux

Teste aí:

sudo apt-get install cowsay

Depois rode:

cowsay Funciona...

O cowsay também pode receber texto na entrada padrão:

date|cowsay

Isso permite usos razoavelmente criativos:

lynx --dump http://news.google.com.br | grep "^\[" | grep -v "»" \
| sed -e "s/.*\]//g" | sort -R | head -n 1|cowsay

Você pode colocar seu Ubuntu para te dar uma dica de Linux toda vez que você abre o terminal, assim:

sudo apt-get install fortunes-ubuntu-server

Depois edite o arquivo ~/.bashrc e inclua no final:

fortune|cowsay

E pronto! Cada vez que você abrir um terminal vai receber uma dica de Ubuntu.

API gratuita de consulta de CEP

Nosso presente de natal para os desenvolvedores do Brasil: API gratuita de consulta de CEP.

A Visie é parceira de tecnologia da Aviso Brasil. Nós fornecemos tecnologia para o Correio Control, e como parte do negócio, precisamos ter a base de endereços sempre atualizada e sincronizada com o Diretório Nacional de Endereços.

Vimos que muita gente oferece aquele cômodo recurso de auto completar o endereço pelo CEP, mas usando bases de dados desatualizadas. Existem até uns serviços pagos que oferecem esses dados.

Por isso, decidimos oferecer um serviço gratuito de consulta de endereços pelo CEP, para que você possa usar em sua aplicação. Os resultados podem ser retornados usando o modelo JSONp, de modo que o próprio navegador do usuário requisite diretamente o endereço de nossos servidores.

Aproveite!

Em tempo: se você faz software que de alguma maneira envia e controla encomendas, você precisa conhecer o Correio Control. É um software de baixo custo para usuários corporativos dos Correios que oferece o controle de faixas de registro, geração de etiquetas e AR, monitoramento e rastreamento estendido, solicitação automatizada de pedidos de informação e indenização, relatórios de status e muito mais.

 

Pequena dica de Python: as classes são dinâmicas

Veja:

>>> class Class:
...   def um(self):
...     return 1
... 
>>> c=Class()
>>> c.um()
1
>>> def dois(self):
...   return 2
... 
>>> Class.dois=dois
>>> c.dois()
2
>>> Class.tres=lambda self:3
>>> c.tres()
3
>>> Class.um=lambda self:'Um modificado.'
>>> c.um()
'Um modificado.'

As classes em Python são completamente dinâmicas. Você pode acrescentar métodos quando quiser e isso se refletirá em todos os objetos criados com aquela classe (mais ou menos como o que você faz em Javascript com prototype.)

Pequena dica de Python: leia os fontes

Python é uma linguagem open-source, com uma extensa biblioteca. E os módulos da biblioteca são escritos em Python. Alguns módulos, como pickle e StringIO, tem versões em C mais rápidas (cPickle e cStringIO) mas as versões em Python são mantidas para que você possa ler os fontes.

Veja como descobrir onde estão os fontes de um módulo qualquer:

>>> import glob
>>> glob.__file__
'/usr/lib/python2.7/glob.pyc'

O nome do arquivo tem a extensão pyc. É um compilado. Tire o último “c” e você terá o caminho do arquivo com o código fonte. Dê uma lida no conteúdo do glob.py, por exemplo, e você deve achar muito simples mas bastante interessante.

Se você está aprendendo Python agora, sempre que for resolver uma tarefa sobre determinado assunto, dê uma olhada no código dos módulos relacionados aquele assunto. Você vai ver como a comunidade Python tem abordado problemas semelhantes aos seus e com certeza vai aprender muito.

Pequena dica de Python: string formatting com locals()

Há muitas situações em que uma função faz cálculos e operações para obter valores e, ao final, deve montar uma string com esses valores. Nesta situação, muita gente monta um dicionário com os valores e usa string formatting para gerar a string a ser retornada. Por exemplo:

# -*- encoding: utf-8 -*-
import string,random

template='''Sugestões para %(nome)s:
 - login: %(login)s
 - email: %(email)s
 - site: www.%(domain)s.com
 - senha: %(passwd)s
'''

def sugere_logins(nome):
    login=nome.split(' ')[0].lower()
    domain=nome.split(' ')[-1].lower()
    email=login+'@'+domain+'.com'
    chars=string.letters+string.digits
    passwd=''.join(random.sample(chars,10))
    dados={'login':login,
           'email':email,
           'nome':nome,
           'domain':domain,
           'passwd':passwd}
    print template % dados

Você pode substituir todo o trecho em que monta o dicionário, usando o resultado da função locals(). A função locals() retorna um dicionário com todas as variáveis locais. No exemplo acima, isso ficaria assim:

# -*- encoding: utf-8 -*-
import string,random

template='''Sugestões para %(nome)s:
 - login: %(login)s
 - email: %(email)s
 - site: www.%(domain)s.com
 - senha: %(passwd)s
'''

def sugere_logins(nome):
    login=nome.split(' ')[0].lower()
    domain=nome.split(' ')[-1].lower()
    email=login+'@'+domain+'.com'
    chars=string.letters+string.digits
    passwd=''.join(random.sample(chars,10))
    print template % locals()

Uso muito esse truque ao trabalhar com web2py, fazendo com que os controllers, ao invés de retornar um dicionário montado por mim, retornem locals().

Pequena dica de Python: rot-13

A dica de hoje não é muito útil. Pelo menos eu nunca usei para nada realmente sério. Mas é bem divertida:

>>> t='All your base are belong to us.'
>>> t.encode('rot-13')
'Nyy lbhe onfr ner orybat gb hf.'

Rot-13 é um encoding comum do Python. Você pode escrever código em rot-13 também, se indicar o encoding do arquivo num cabeçalho:

# -*- encoding: rot-13 -*-
vzcbeg fgevat
sbe v va enatr(20):
    cevag fgevat.nfpvv_ybjrepnfr[:v]

Salve o conteúdo acima no arquivo rot13.py e você poderá executar:

$ python rot13.py

Divertido, não?

Pacote Ubuntu: cclive

O pacote cclive, para download de vídeos do YouTube na linha de comando, é uma reescrita do clive mais eficiente, com menor consumo de memória e menos dependências. Para instalar:

$ sudo apt-get install cclive

E para usar:

$ cclive http://www.youtube.com/watch?v=8fvTxv46ano

Isso vai baixar o vídeo na pasta atual. Simples e indolor. Mas qual a vantagem de usar a linha de comando em relação a uma extensão no navegador, onde você não precisa digitar comandos? Com a linha de comando é possível automatizar as tarefas. Criei um script que recebe um nome de usuário do YouTube e baixa os últimos 15 vídeos publicados. Chamei o arquivo de massclive. Veja o código fonte:

mkdir -p $1

lynx --dump http://www.youtube.com/user/$1/feed | \
  grep youtube.com/watch | \
  sed -e "s/.* //" | \
  sed -e "s/&.*//" | \
  sort -u | \
  while read url
  do
    cclive -c --output-dir $1 $url
  done

E você pode usar assim:

$ ./massclive maninthearenatv