Arquivo para outubro \11\UTC 2011

Escolhendo o canal do Wi-Fi

Algo muito comum é instalar um roteador Wi-Fi num ambiente pequeno e, ainda assim, ter problemas com a velocidade da conexão.

Pode acontecer de existirem vários outros roteadores de vizinhos usando o mesmo canal e possivelmente com um sinal mais forte (aquele povo que compra antenas enormes na Uruguaiana ou Santa Ifigênia) estarem fazendo a sua placa wireless perder muitos pacotes.

Todo roteador Wi-Fi vem com uma página de configuração que permite escolher o canal da faixa de 2.4GHz em que vai operar.
Caso não se lembre como acessar ou se não foi você quem instalou, provavelmente olhando qual o gateway da sua máquina você acha o IP do roteador (algo como 192.168.0.1).

Na hora de escolher o canal ideal para sua conexão, é preciso saber que parte da banda os roteadores mais próximos estão localizados e, para isso, existe um excelente aplicativo gratuito chamado InSSIDer que fornece informações bem detalhadas.

Em uma das abas do programa, ele mostra os canais das redes ao alcance, assim como suas intensidades. Ele também mostra a intensidade ao longo do tempo além de outras informações como fabricante, velocidade da rede, largura do canal etc.

Assim, é fácil escolher o canal do seu Wi-Fi apenas verificando qual está menos utilizado (geralmente as extremidades).

Outra coisa é, se você tem um Wi-Fi 802.11n de 300mpbs (bastante comum nos roteadores de 2011) ele pode ocupar o dobro da banda no espectro por utilizar 2 canais, o que melhora a qualidade geral da sua internet, mas causa mais interferência na dos outros :).

Esse é um programa que vale a pena ter instalado.

Anúncios

Python 3 – exec e outras mudanças

Já tem um tempo que tento usar somente Python 3 para meus projetos em Python, mas, como muita gente ainda está presa em versões antigas (como o pessoal do CentOS que há um mês mudou do Python 2.4 para o ainda defasado 2.6), sou obrigado a trabalhar com os dois ambientes.

Portar pequenos programas de uma versão para outra pode ser bastante simples (como no Txt2Tags que precisei de umas 2 ou 3hs para fazer funcionar) quando já se conhece os possíveis problemas e suas soluções, mas nem tudo está bem documentado.

Claro que tudo isso seria muito mais difícil se não houvesse script chamado 2to3.py que vem junto com as versões mais novas do interpretador para automatizar o processo. O problema que existem coisas que ele é incapaz de traduzir ou que precisam de mudanças mais bruscas no código para que funcionem.

Por algum motivo, o site “Dive into Python 3” que tinha uma versão online do livro homônimo foi removido do ar e perdi a melhor referência para o tópico que existia, ** Encontrei um novo mirror do Dive into Python 3 **

Também existem outros bons textos por ai.

Algumas das mudanças mais importantes na nova versão são os iteradores usados em lugares que antes retornavam listas, o uso de unicode por padrão (que na minha opinião já vale por todo o trabalho de portar código) e a troca de algumas palavras-chaves (statements) por funções e vice-versa.

Sobre essa última mudança, as palavras-chave tem o poder de mudar o local em que se encontram enquanto outros nomes podem significar qualquer coisa que o programador queira e só podem ser verificados em tempo de execução, não podendo transformar o ambiente.

Por exemplo, o comando yield faz com que o a função que o contenha seja transformada num gerador mesmo que ele nunca seja executado ou tenha bytecode para isso!

def gerador():
    if 0:
        yield

Neste código acima, o interpretador vai ver que o if nunca será executado e não vai gerar bytecode para nada dentro dele (no caso o yield), mas a função não vai retornar o implícito None quando for chamada. Ela vai retornar um gerador vazio que pode ser usado num loop for.

Usando o módulo dis para desmontar bytecode vemos que a função só retorna None, mas ela vai ter um flag para mostrar sua utilidade:

>>> dis.dis(gerador)
  2           0 LOAD_CONST               0 (None)
              3 RETURN_VALUE

Ainda sobre isso, True, False e None agora são palavras reservadas e que não podem ser modificadas, fazendo com que, se o exemplo acima fosse feito com False ao invés de 0, ele geraria bytecode no Python 2, mas não no Python 3!

No sentido contrário, as palavras-chave print e exec do Python 2 agora são funções e não podem mais alterar seu ambiente.

No caso do print, não tem problema algum e a sintaxe ficou bem melhor, mas o exec (que normalmente seu uso não é uma boa prática de programação) pode ter um comportamento bem diferente nas duas versões do interpretador.

Essa informação não vai ser encontrada na documentação do Python (apenas alguns avisos que não explicam bem a situação) e geralmente a pessoa vai procurar saber disso quando bater de cara com esse problema e nada funcionar.

Olhe o código abaixo (Não tome como exemplo de boa programação):

a = 1
def f():
    exec("a = 2")
    print(a)

f()
print(a)

No Python 2, a função vai imprimir “2” e o outro print vai imprimir “1”, como esperado. No Python 3, o número “1” vai ser impresso nos dois casos.

O que aconteceu?

O meu amigo dis mostra como a variável “a” é chamada no bytecode para impressão dentro da função:

Python 2:

3            8 LOAD_NAME                0 (a)

Python 3:

3           13 LOAD_GLOBAL              2 (a)

Como o Python 3 não consegue ver nenhum a dentro da função, ele assume que é uma palavra definida globalmente e vai embora. No Python 2, é percebida a existência da palavra exec e transforma a busca por um nome sendo primeiro no namespace local e, se não encontrar, no namespace global.

O que, por um lado traz o resultado “desejado”, também faz todos os acessos a funções e variáveis serem mais lento.

Soluções:
1 – Não usar exec.

Praticamente sempre é possível fazer uma solução sem exec que seja simples, mas se for necessário, é preciso tomar cuidado com essa mudança ou passar um segundo parâmetro para a função dizendo em que namespace você quer se o resultado seja avaliado e usar a informação nele.

Normalmente, ninguém usa exec para situações como a que eu mostrei, mas para gerar conteúdo (funções, classes, subclasses, etc) em tempo de execução e muitas vezes existem ferramentas melhores, como as metaclasses e os decoradores.