Sou fã do seriado Lost e ansioso pela próxima temporada encontrei o contador abaixo.
E você, está contando os dias também?
Se por um acaso do destino você precisar alterar ou começar do zero um arquivo batch (.bat) e ainda necessitar receber argumentos pela chamada do arquivo, muito provavelmente você irá utilizar aspas no argumento se ele for um caminho de alguma pasta ou diretório.
Se esse caminho não possuir espaços, tudo será tranquilo, você provavelmente irá utilizar %1 e receberá o argumento corretamente, mas se o caminho possuir espaços, você vai colar aspas duplas pra passar o parâmetro corretamente e surpresa não vai conseguir concatenar esse caminho com nada.
Depois de muita pesquisa do google fica a dica então: %~1 retira as aspas do caminho facilitando para você fazer algo do tipo:
"%~1\programa.exe"
Lembrando que segundo a fonte isso vale apenas para NT 4 (SP6) pra cima.
Continuando o post anterior[1], além do pdb[2] que é totalmente via linha de comando, há o winpdb[3] que possui uma interface gráfica para facilitar a depuração.
Instalá-lo é muito fácil, se você possui easy_install é só executar:
sudo easy_install winpdb
Se você não tem easy_install, mas tem apt-get:
sudo apt-get install winpdb
Se você não tem nada disso ainda dá pra baixar pelo site[3] e funciona no Windows também, mas eu não testei.
Usarei como exemplo o código criado pelo post anterior, é um projeto bem simples com apenas uma view para atestar o poder do debug.
Lembra da nossa view, ela é simples assim:
def hello(request):
a = 2
b = 3
c = [1,2,3]
c.pop()
d = soma(3,4)
response = HttpResponse("Hello World")
return response
Como o winpdb possui a funcionalidade de adicionar breakpoints eu tirei aquele código de debug do pdb senão eles conflitariam entre si.
Abra o winpdb:
A interface dele é bem simples, ficará mais clara quando estivermos executando alguma coisa.
Vá até File->Launch e na janela aberta escolha o manage.py do projeto que vamos depurar, por fim adicione runserver --noreload no comando e então clique em OK para iniciar o servidor.
O seu winpdb deve ficar parecido com a imagem abaixo, além de um terminal que será aberto pelo próprio winpdb.
Antes de continuar qualquer coisa, vá até File->Open Source e na janela aberta escolha o arquivo views.py, adicione um breakpoint na linha a = 2 clicando à direita do número da linha. Tente acessar a URL que executa a view hello e volte ao winpdb, você verá algo como abaixo (a diferença é que eu já andei duas linhas no código):
Essa imagem é bem interessante pois mostra valores das variáveis, um console escondido abaixo do código, o arquivo em que o debugger se encontra, controles de avanço do debug, etc.
Avance com Control->Next até a chamada de soma e entre com Control->Step Into, avance duas linhas e você ficará assim:
As variáveis do escopo local mudaram, o debugger continua no views.py mas agora dentro da função soma, dê Control->Return para ir até antes da função retornar pro escopo de hello.
Com Control->Next vá até antes da linha que executa return response e vamos brincar um pouco com o console que se encontra abaixo do código-fonte:
Como você pode ver na imagem, o comando v (de eval) seguido de uma expressão retorna o valor da expressão, já o comando x (de exec) seguido de uma expressão executa a expressão informada.
Vamos fazer igual ao post anterior e verificar as propriedades de response:
Na imagem acima, executamos um dir na variável response, exibimos seu content com v, alteramos o content com x e por fim com Control->Go visualizamos o resultado no navegador:
Para saber de mais funcionalidades que o winpdb pode te oferecer dê uma olhada no tutorial[4] (bem completo por sinal) que se encontra na própria wiki[5] deles.
[1] – http://blog.danilocabello.com/arquivo/debugando-no-django/
[2] – http://docs.python.org/library/pdb.html
[3] – http://winpdb.org/
[4] – http://winpdb.org/cgi-bin/moin.cgi/WinpdbTutorial
[5] – http://winpdb.org/cgi-bin/moin.cgi/FrontPage
Bem que você tentou, releu o código diversas vezes, escreveu um monte de prints, mas não conseguiu descobrir o que está causando aquele bug indesejado. É chegada a hora de debugar seu código, a seguir darei algumas dicas de como debugar com pdb seu projeto em Django[1].
Primeiramente, debugar um projeto em Python[2] e debugar um projeto em Django não tem muita diferença, a coisa toda é muito parecida, você só precisa do pontapé inicial para se virar dali pra frente.
Para aprender como utilizar o pdb[3] (vulgo Python Debugger) crie um novo projeto chamado djdebug, logo em seguida crie um arquivo vazio chamado views.py na própria raiz do projeto, ficando com a seguinte estrutura de arquivos:
djdebug - __init__.py - manage.py - settings.py - urls.py - views.py
No arquivo views.py cole o seguinte código:
from django.shortcuts import HttpResponse
def soma(a,b):
arg1 = a
arg2 = b
soma = arg1 + arg2
return soma
def hello(request):
a = 2
b = 3
c = [1,2,3]
c.pop()
d = soma(3,4)
response = HttpResponse("Hello World")
return response
Como podemos ver o arquivo contém uma função soma, que não faz nada de muito complexo e uma função hello que retorna uma response com o conteúdo "Hello World".
No arquivo urls.py importe a view hello e adicione uma URL para podemos acessá-la:
from views import hello
urlpatterns = patterns('',
...
(r'^hello', hello),
)
Execute o servidor de testes, navegue até http://localhost:8000/hello e verifique que está tudo funcionando:
./manage runserver
Suponha que há um bug em alguma parte da view hello e então adicione o código para possibilitar o debug:
def hello(request):
a = 2
import pdb
pdb.set_trace()
...
Apenas para esclarecer, o import pdb importa o Python debugger, já o pdb.set_trace() serve pra colocar um breakpoint no código, há maneiras de se colocar um breakpoint no código sem alterá-lo através do próprio pdb[3].
Execute o servidor de testes mas desta vez adicione o parâmetro necessário para evitar recarregamento automático do código-fonte:
./manage runserver --noreload
Abra novamente a view hello no seu navegador, ela ficará parada e no terminal que você iniciou o servidor o pdb[3] estará parado esperando por comandos:
> /home/.../djdebug/views.py(13)hello() -> b = 3 (Pdb)
Vamos começar, temos um comando interessante que é o l (de list, lista o código na região do debugger) que lista onde se encontra o debugger:
(Pdb) l
8
9 def hello(request):
10 a = 2
11 import pdb
12 pdb.set_trace()
13 -> b = 3
14 c = [1,2,3]
15 c.pop()
16 d = soma(3,4)
17 response = HttpResponse("Hello World")
18 return response
É importante notar que o debugger se encontra no exato momento antes de executar a linha apontada pela seta, isto é, se executarmos p (de print, imprime a expressão passada como argumento) para inspecionarmos a variável b, ela não estará definida:
(Pdb) p a
2
(Pdb) p b
*** NameError: NameError("name 'b' is not defined",)
Vamos para próxima linha com n (de next, segue para a próxima linha):
(Pdb) n > /home/.../djdebug/views.py(14)hello() -> c = [1,2,3] (Pdb) p b 3
Agora sim b já possui valor, vamos avançar até a chamada da função somar:
(Pdb) n > /home/.../djdebug/views.py(15)hello() -> c.pop() (Pdb) <enter> > /home/.../djdebug/views.py(16)hello() -> d = soma(3,4)
A partir do primeiro n, enter executará n novamente. Como nós não sabemos se o problema da view hello é a função somar, vamos entrar na função somar com s (de step into, entra na função, ou seja, passo a dentro) e verificar se está tudo certo:
(Pdb) s --Call-- > /home/.../djdebug/views.py(3)soma() -> def soma(a,b): (Pdb) l 1 from django.shortcuts import HttpResponse 2 3 -> def soma(a,b): 4 arg1 = a 5 arg2 = b 6 soma = arg1 + arg2 7 return soma 8 9 def hello(request): 10 a = 2 11 import pdb
Como podemos ver o debugger se encontra na entrada da função soma, damos uma “olhada por cima” e saímos da função com up (de up, sobe uma chamada na pilha):
> /home/.../djdebug/views.py(4)soma() -> arg1 = a (Pdb) n > /home/.../djdebug/views.py(5)soma() -> arg2 = b (Pdb) n > /home/.../djdebug/views.py(6)soma() -> soma = arg1 + arg2 (Pdb) u > /home/.../djdebug/views.py(16)hello() -> d = soma(3,4)
Como podemos ver, voltamos a view hello, vamos avançar até antes de retornar a resposta da requisição e atestar umas coisinhas:
(Pdb) n
> /home/.../djdebug/views.py(17)hello()
-> response = HttpResponse("Hello World")
(Pdb) n
> /home/.../djdebug/views.py(18)hello()
-> return response
(Pdb) dir(response)
['__class__', '__contains__', '__delattr__', '__delitem__', '__dict__', '__doc__', '__format__', '__getattribute__', '__getitem__', '__hash__', '__init__', '__iter__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', '_charset', '_container', '_convert_to_ascii', '_get_content', '_headers', '_is_string', '_set_content', 'close', 'content', 'cookies', 'delete_cookie', 'flush', 'get', 'has_header', 'items', 'next', 'set_cookie', 'status_code', 'tell', 'write']
(Pdb) response.content
'Hello World'
(Pdb) response.content = 'Django debugado'
(Pdb) c
Como podemos verificar, o pdb[3] fornece um shell do Python[2] você pode executar dir, verificar valores de variáveis e até mudar conteúdo de variáveis (poder e perigo andando juntos), por fim executamos c (de continue, para continuar a execução), veja o resultado no seu navegador, a mensagem "Hello World" foi trocada por "Django debugado".
Recomendo a leitura do paper “Debugging in Python”[4] para mais alguns detalhes do pdb[3]. É muito interessante saber “brincar” com o shell do Python e do Django, com essas ferramentas fica mais fácil rastrear o chato do bug.
[1] - http://www.djangoproject.com/
[2] – http://www.python.org/
[3] – http://docs.python.org/library/pdb.html
[4] – http://www.ferg.org/papers/debugging_in_python.html
Estava procurando por uma forma de bloquear e-mails duplicados no django.contrib.auth[1], eis que encontro o projeto “plugável” django-registration[2] que não só implementa essa funcionalidade como e-mails de confirmação e a confirmação ainda expira conforme um número de dias definido nas suas settings.py.
A aplicação é muito completa, possui testes e exige o mínimo de conhecimento em Django que é saber criar templates. Ao baixar a aplicação eu pensei que iria ter que adaptar um monte de coisa para se encaixar na minha aplicação, que nada, a aplicação está no limite da plugabilidade que o Django investe.
Give a try.
[1] – http://docs.djangoproject.com/en/dev/topics/auth/#topics-auth
[2] – http://bitbucket.org/ubernostrum/django-registration/
Tags: Django
Dica rápida, se você costuma usar Python para fazer scripts e toda vez que vai reutilizar um deles tem que olhar o código fonte pra lembrar como usar, você precisa conhecer o optparse[1].
Dê uma olhada na documentação[1], que é bem completa e no exemplo abaixo, para ver o quão prático é utilizar este módulo.
def fatorial(n):
resultado = 1
while n > 0:
resultado = n*resultado
n -= 1
return resultado
if __name__ == '__main__':
from optparse import OptionParser
parser = OptionParser()
parser.add_option('-a', '--arquivo',
dest='arquivo', help='arquivo com os fatoriais desejados')
parser.add_option('-v', '--valor', type='int',
dest='valor', help='valor a ser calculado')
(options, args) = parser.parse_args()
if options.valor and options.arquivo:
parser.error("opcoes -v e -a sao mutualmente exclusivas")
elif options.valor:
print "fatorial(%s) = %s" % (options.valor, fatorial(options.valor))
elif options.arquivo:
for linha in open(options.arquivo):
linha = int(linha)
print "fatorial(%s) = %s" % (linha, fatorial(linha))
else:
parser.error("nenhuma opcao foi escolhida, execute com -h para ajuda")
[1] – http://docs.python.org/library/optparse.html
Tags: Python
Através da discliplina MC750, foi indicada a análise do ambiente de programação Alice (www.alice.org). Trata-se de uma aplicação destinada ao desenvolvimento de animações, focada ao aprendizado.
Acessando-se o site do programa, o acesso ao download é simples, embora o arquivo baixado não seja um instalador, sendo o aplicativo pronto para o uso. Sem uma instalação, a criação de atalhos para o uso deve ser feita manualmente, o que dificulta o uso para os mais leigos.
As primeiras informações que se tem ao iniciar o programa nos dizem a respeito de tutoriais – altamente recomendados, já que o programa dá a impressão de ter mais opções do que se saiba mexer. Iniciando-se o primeiro tutorial, temos os passos básicos da aplicação, sendo exibidos de forma clara, e as opções não usadas no momento não são acessíveis, facilitando a aprendizagem.
Os tutoriais são simples e bem informativos. Seguindo-se passo a passo por uma série de ferramentas, não há muito onde errar.
Embora algumas orientações possam ser mal implementadas, de forma que a opção selecionada não é a requerida. Neste caso, o tutorial pára, mesmo que você saiba que fez o que é certo.
Neste caso, a saída parece “forçar” o tutorial a continuar, clicando-se no Next na parte superior da tela (mesmo este aparentando não ser acessível). Isso se apresenta com pouca freqüência, nos quatro tutoriais disponíveis.
Cumprindo os tutoriais, tentamos caminhar por conta própria dentro do programa, embora o excesso de informações disponível ainda seja um pouco confuso. Mesmo assim, com certa facilidade as animações podem ser montadas, embora se encontre limitações, sendo essas do próprio programa ou porque não se sabe como resolvê-las – não há um arquivo de ajuda, só animações pré-prontas, onde se poderia verificar a existência de novas funcionalidades.
Tags: design, interfaces, unicamp
O conceito de interfaces vai além da relação homem-máquina. As interfaces estão presentes em tudo que possui mais de um componente formador: porca-parafuso, porta-parede, calçado-pé. Diferentes interfaces proporcionam usos distintos, mas não necessariamente distintos semanticamente. Nota-se que, como em interfaces computacionais, o objetivo é permitir sempre ao usuário máxima transparência do sistema que opera por baixo e proporcionar uso agradável do objeto/ferramenta.

Iguais quanto ao uso, diferentes quanto a forma
Dentro do próprio ramo computacional, as interfaces estão presentes em áreas completamente distintas. Um circuito integrado deve ser visto como uma caixa preta pelo resto do sistema, que age nesta abordagem como o usuário ou cliente dos serviços oferecidos por tal módulo. Saindo do baixo para o alto nível encontramos as telas touch e hologramas fisicamente manuseáveis, que são duas tecnologias até a pouco tidas como futuristas mas que atualmente tornaram-se quotidianas.
Mais incrível ainda é notar que tais interfaces inovadoras – sejam programas ou físicas – não estão mais confinadas ao computador pessoal (desktop ou laptop), o que obrigava a forma de apresentação da interface estar adaptada ao equipamento. Hoje a situação se inverteu. Primeiro temos a definição do tipo de interface adequada para uma dada aplicação e daí os hardwares são desenvolvidos de forma a oferecer recurso computacional para aquela demanda. Tal tratamento do objetivo inovador fornece recursos para aquela que se mostra a área mais carente em termos tecnológicos: a acessibilidade. Indubitavelmente a sociedade tem sido omissa – e não raras vezes preconceituosa – com o tratamento daqueles que não possuem as mesmas capacidades da maioria dos homens.
Interessante saber que é justamente no atendimento dessas minorias que o design de interfaces se mostra mais promissor. A capacidade da máquina de interpretação de gestos, fala e escrita em braile fornece um mundo de informação e interatividade para tais usuários. Na verdade, os transforma em usuários, já desde muito tempo eles não tecnologicamente inclusos.
Por Plínio Sandes dos Santos
Durante o curso de computação na Unicamp, e acredito que seja assim em qualquer outro curso semelhante de outras instituições, me acostumei a enxergar o software que estava desenvolvendo a partir de um único ponto de vista: do desenvolvedor. Após cursar inúmeras disciplinas MCxxx, minha única preocupação era que o software proporcionasse total integridade e eficiência máxima. O usuário final nem era levado em consideração até por que esse usuário se resumia geralmente a mim e ao professor da disciplina. Enfim, nós somos introduzidos à disciplina MC750.
Inicialmente, são apresentados diversos problemas de interfaces de situações do cotidiano como o formato equivocado de uma torneira de banheiro público e disposição confusa de botões num controle remoto. Percebi que o design não é só uma questão de estética visual, mas também é muito importante para que permita um uso intuitivo. Também foi reforçada a noção de que a grande maioria das pessoas não são usuários avançadas de computador como nós e que os usuários dos softwares que nós desenvolvemos não têm a obrigação de conhecer todas as suas funcionalidades. Eu mesmo já sofri com softwares que fui obrigado a usar durante a graduação, como Max Plus II e Spice, dois nomes que trarão lembranças nada agradáveis a qualquer aluno da turma devido às suas interfaces extremamente irritantes.
Passando para problemas de interfaces específicos de informática, conheci as heurísticas de Nielsen. Sabendo avaliar uma interface heuristicamente, vi que para mim era tão intuitivo procurar a opção de salvar um documento no canto superior esquerdo do programa como empurrar uma porta cuja maçaneta tem forma plana. As heurísticas me deram uma idéia concreta de como deve ser aparentar um programa, e, principalmente, os problemas básicos que não devo cometer ao desenvolver a interface de um software, seja qual for a utilidade dele.
Luis Fernando Lopes Iwasaki
Em quase três anos de Egenharia de Computação, minha visão sobre a área saiu da de usuário final para a de programador. O problema desse processo é que o foco passa a ser na funcionalidade: um programa recebe uma tarefa e deve completá-la. Durante esse tempo, a noção de interface se resumia à linha de comando.
Porém, neste semestre, com a disciplina MC750, tive contato com o aspecto da interface entre usuário e programa. Isso retoma a visão de usuário final que possuía, mas de maneira muito mais crítica, já que falhas de interface são definidas com heurísticas, e não apenas com a sensação de que “algo está errado”. Embora muitas das heurísticas não apresentem fronteiras bem definidas, elas permitem delinear o que pode ser melhorado num projeto.
O problema do programador é também subestimar os problemas de interface que ele encontra, de forma a sempre se acostumar a ter um “atalho” para resolver o problema, o que não pode ser considerado para o usuário final. Estes, querem clareza, fácil uso mas ao mesmo tempo acessar tudo o que puderem. E cabe ao programador manter essa visão enquanto aprimora seu projeto, visão esta desenvolvida com a disciplina.
Outro aspecto novo para mim foi o de acessibilidade. A tendência é que se você não tem o problema, você não pensa em como seria se o tivesse. Como programador, é minha responsabilidade idendificar no projeto o que pode ser facilitado e simplificado, além do que eu considero já suficiente. Isso permite que o seu projeto possa ser alcançável para todos.
Saindo para o mercado, espero utilizar esses conceitos aprendidos para que o que eu desenvolva, seja claro não só para usuários avançados, mas para todos os que se interessem pelo que foi desenvolvido. A funcionalidade também é importante, mas ela não é nada sem a facilidade de uso.
Josué Andrade
Tags: interfaces, unicamp