Customizando o prompt do IPython 5+

Há poucos meses atrás foi lançada a versão 5 do IPython. O shell que antes já era super legal, agora ficou mais interessante ainda, com syntax highlighting no código digitado e um esquema de completação inline usando umas listinhas bem convenientes:

screen-shot-2016-09-18-at-8-41-50-am

Porém, a forma de configuração do prompt mudou. Algumas das dicas apresentadas no post Sintonia Fina no IPython não se aplicam mais. Assim, vou mostrar aqui como fazer para que o seu IPython 5+ fique com aparência semelhante à abaixo:

screen-shot-2016-09-18-at-8-40-12-am

O que mudou basicamente é que ao invés de simplesmente definir a string que será usada como prompt em um atributo, agora é preciso implementar uma subclasse de Prompts, com alguns métodos para alterar o comportamento do seu prompt:

from IPython.terminal.prompts import Prompts, Token


class MyCustomPrompt(Prompts):

    def in_prompt_tokens(self, cli=None):
        return [(Token.Prompt, '>>> '), ]

    def out_prompt_tokens(self, cli=None):
        return [(Token.Prompt, ''), ]

    def continuation_prompt_tokens(self, cli=None, width=None):
        return [(Token.Prompt, ''), ]

No exemplo acima, customizei os prompts de entrada (de In [1]: para o tradicional >>>), de saída ( de Out[1]: para nada) e de continuação (de ...: para nada).

O legal dessa nova abordagem é que agora temos mais flexibilidade pra customizar os prompts, colocando valores dinâmicos dentro deles se quisermos.

Como configurar seu prompt

A configuração do IPython se dá através de perfis, então vamos começar criando o perfil default:

$ ipython profile create

Isso irá criar um diretório ~/.ipython com a seguinte estrutura:

.ipython
├── extensions
├── nbextensions
└── profile_default
    ├── ipython_config.py
    ├── ipython_kernel_config.py
    ├── log
    ├── pid
    ├── security
    └── startup
        └── README

Agora salve a classe MyCustomPrompt em um arquivo ~/.ipython/my_custom_prompt.py e depois disso edite o arquivo ~/.ipython/profile_default/ipython_config.py para que tenha o seguinte conteúdo:

from my_custom_prompt import MyCustomPrompt


c = get_config()

c.TerminalInteractiveShell.prompts_class = MyCustomPrompt
c.TerminalIPythonApp.display_banner = False
c.TerminalInteractiveShell.separate_in = ''

Pronto, agora o seu IPython 5+ deverá se parecer com aquele que mostrei no screenshot lá no começo do post.

Se você estiver usando uma versão anterior do IPython, verifique meu post anterior sobre o mesmo assunto: https://pythonhelp.wordpress.com/2013/12/29/sintonia-fina-do-ipython/

Confira as minhas configurações do IPython em: https://github.com/stummjr/dotfiles/tree/master/ipython

Sintonia fina do IPython

Para IPython 5+, veja o post mais recente.

Quem já usou o IPython alguma vez sabe que ele é um tanto quanto “espaçoso”. Cada comando digitado gera uma nova linha, além de ele usar um prompt de entrada e saída com a contagem dos comandos digitados. Se, assim como eu, você não curte o visual do IPython padrão, este texto é para você.

Por padrão, o IPython se apresenta assim:

ipython1

Veja quantos espaços em branco. Ele é bem diferente do shell Python padrão, que é bem menos espaçoso.

Para deixá-lo mais parecido com o shell Python basicão, basta dar uma “tunadinha” nele. Em outro post, já mostrei como configurar alguns aspectos do IPython. Neste post, vou apresentar algumas configurações adicionais que podem ser feitas. Ao final dele, seu IPython vai ficar parecido com:

ipython2

Configurando o IPython

Antes de qualquer coisa é preciso criar um perfil, através do seguinte comando no shell do seu sistema operacional:

$ ipython profile create

Isso irá criar um perfil chamado de default e todas as configurações desse perfil estarão no diretório ~/.config/ipython/profile_default/ (ao menos no Ubuntu).

Feito isso, agora você pode editar o arquivo de configurações do IPython (~/.config/ipython/profile_default/ipython_config.py). Ele está repleto de linhas de código Python comentadas, mas vou me deter aqui apenas àquelas que descomentei e customizei.

Desabilitar o banner de apresentação

Toda vez que é iniciado, o IPython mostra um banner parecido com:

Python 2.7.4 (default, Sep 26 2013, 03:20:26) 
Type "copyright", "credits" or "license" for more information.

IPython 0.13.2 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object', use 'object??' for extra details.

Depois de ver duas ou três vezes, já decoramos essas informações e elas não são mais necessárias. Para desabilitar a apresentação dessas informações ao iniciar o IPython, utilizei a seguinte definição:

c.TerminalIPythonApp.display_banner = False

Removendo os \n entre as entradas

Uma das coisas mais irritantes no IPython é a quantidade de espaços em branco que ele coloca na tela. Muitos desses espaços são gerados pela separação entre as entradas através de um caractere de \n. Dá pra ajeitar isso, colocando um caractere vazio como separador:

c.TerminalInteractiveShell.separate_in = ''

Removendo a confirmação de fechamento

O IPython sempre pergunta se você deseja mesmo fechá-lo ao pressionar C-d. É claro que eu quero te fechar, ou tu tá achando que pressionei Ctrl e depois d sem querer? Dá pra evitar essa chateação com:

c.TerminalInteractiveShell.confirm_exit = False

Permitindo ao IPython modificar o título do terminal

Isso pode ser bem útil pra quem costuma ficar com várias abas de terminal abertas. Habilite isso com a seguinte linha:

c.TerminalInteractiveShell.term_title = True

Customizando o prompt de saída

Por padrão, linhas que contenham saída são precedidas por Out [x]:. Isso me incomodava um pouco, então resolvi alterá-lo e deixá-lo mais parecido com o shell padrão. Você também pode fazer isso com a seguinte linha:

c.PromptManager.out_template = ''

Customizando o prompt de entrada

O prompt de entrada no IPython apresenta o texto In [x]:. Para fazer com que o prompt de entrada seja igual ao clássico >>> do shell padrão, faça:

c.PromptManager.in_template = '>>> '

Completação por tab gulosa

Para habilitar a completação em resultados de chamadas de funções, ou em elementos de sequências, basta habilitar a configuração abaixo:

c.IPCompleter.greedy = True

Atenção: comentários no arquivo advertem que pode ser um pouco perigoso habilitar a configuração acima, pois para poder completar baseando-se no resultado de uma chamada de função, o ipython terá que chamá-la.

O ipython_config.py completo

# Configuration file for ipython.
c = get_config()

# Whether to display a banner upon starting IPython.
c.TerminalIPythonApp.display_banner = False

# Remove those annoying newlines between each input
c.TerminalInteractiveShell.separate_in = ''

# Set to confirm when you try to exit IPython with an EOF (Control-D in Unix)
c.TerminalInteractiveShell.confirm_exit = False

# Enable auto setting the terminal title.
c.TerminalInteractiveShell.term_title = True

# Output prompt.
c.PromptManager.out_template = ''

# Bring back the classic Python REPL prompt.
c.PromptManager.in_template = '>>> '

# Activate greedy completion
# This will enable completion on elements of lists, results of function calls,
# etc., but can be unsafe because the code is actually evaluated on TAB.
c.IPCompleter.greedy = True

Sugestões?

Se tiver mais alguma sugestão, envie um comentário.

Java ou Python? Jython!

O interpretador Python padrão, também conhecido como CPython, é implementado em linguagem C, e nada mais é do que um programa que roda diretamente sobre o hardware. Além do CPython, existem implementações alternativas do interpretador Python. Talvez a mais popular dentre elas, o Jython é escrito em Java e roda sobre a JVM. Além de poder ser executado em qualquer ambiente que possua uma JVM instalada, Jython possibilita que APIs Java sejam utilizadas em Python. Ou seja, tenta unir o melhor de dois mundos: a rapidez no desenvolvimento de Python com a enorme quantidade de APIs maduras disponíveis para Java. Por se tratar de um interpretador Python, a sintaxe dos programa escritos para rodar sobre o Jython é idêntica a dos programas escritos para rodar sobre o CPython.

Mas como funciona isso?

É bem simples, basta importar as libs Java e sair usando, com a sintaxe de Python. Veja:

>>> from java.lang import Math, System
>>> raiz = Math.sqrt(9)
>>> System.out.println(raiz)
3.0

O trecho de código acima foi executado no interpretador Jython (disponível em jython.org).

Viu que maravilha? Importamos e executamos o código de bibliotecas Java, mas com a sintaxe de Python!

Herança

Outra coisa fantástica é a possibilidade de estender classes Java usando Python. Por exemplo, considere a seguinte classe Java (copiada descaradamente daqui):

public class Bicycle {

    public int cadence;
    public int gear;
    public int speed;

    public Bicycle(int startCadence, int startSpeed, int startGear) {
        gear = startGear;
        cadence = startCadence;
        speed = startSpeed;
    }

    public void setCadence(int newValue) {
        cadence = newValue;
    }

    public void setGear(int newValue) {
        gear = newValue;
    }

    public void applyBrake(int decrement) {
        speed -= decrement;
    }

    public void speedUp(int increment) {
        speed += increment;
    }
}

Se quisermos estender a classe acima, especializando-a para representar um tipo específico de bicicleta, como uma mountain bike, podemos estendê-la como se fosse uma classe Python. Veja abaixo o exemplo (MountainBike.py):

import Bicycle

class MountainBike(Bicycle):

    def __init__(self, seatHeight, startCadence, startSpeed, startGear):
        super(Bicycle, self).__init__(self, startCadence, startSpeed, startGear)
        self.seatHeight = seatHeight

    def setHeight(self, seatHeight):
        self.seatHeight = seatHeight

Se quiser testar os exemplos acima, não esqueça de:

  1. Compilar o arquivo Bicycle.java com um compilador Java:
    • javac Bicycle.java
  2. Rodar o arquivo MountainBike.py com o jython:
    • jython MountainBike.py

Todo programa Python vai rodar no Jython?

Não. Alguns programas rodam somente na implementação padrão do interpretador, pois dependem de módulos específicos que foram escritos em C e que ainda não foram portados para Java. Mas, de acordo com o FAQ, a grande maioria já está disponível.

Por que usar Jython?

Odeia a sintaxe e exigências semânticas de Java, mas não desgruda por causa das APIs que ela oferece? Manda ver com Jython! As possibilidades são muitas! Que tal reaproveitar aquela classe Java que você criou há tempos e que vem quebrando um galhão nos seus projetos? Basta importá-la como se fosse um módulo Python e chamar seus métodos.

Outros casos de uso para Jython podem ser protótipos de aplicações explorando bibliotecas Java, implantação de aplicações Django em containers Java como Tomcat/Jboss/Glassfish, usando recursos desses ambientes e integrando com outras aplicações Java já existentes, e por último mas não menos importante: tornar sua aplicação Java extensível permitindo que os usuários adicionem comportamento escrevendo scripts em Python.

Mais informações

Obrigado ao Elias Dorneles pela colaboração!

Dicas de produtividade no IPython

O IPython é o meu shell Python favorito. É cheio de recursos que facilitam o dia-a-dia de quem passa parte de sua vida imerso em um shell Python. Neste post, vou listar alguns recursos que me ajudam bastante diariamente.

Recuperando o resultado da última operação

É coisa bem comum estar em uma sessão no shell Python, testar uma determinada operação e logo depois perceber que queria atribuir o resultado daquela operação para alguma variável. No IPython é barbada, com o _:

In [5]: 10 * 2 + 4 * 4
Out[5]: 36
In [6]: print _
36
In [7]: x = _
In [8]: print x
36

Ou seja, o resultado da execução do último comando é sempre referenciado pelo _ (underscore). Além disso, dois underscores referem-se sempre ao resultado obtido pela execução do penúltimo comando e três underscores ao resultado do antepenúltimo comando. Assim:

  • _: resultado do último comando.
  • __: resultado do penúltimo comando.
  • ___: resultado do antepenúltimo comando.

Isso é particularmente útl quando estamos imersos em uma sessão de descoberta usando o IPython. Torna o processo muito mais ágil. Veja:

In [18]: 1
Out[18]: 1
In [19]: 2
Out[19]: 2
In [20]: 3
Out[20]: 3
In [21]: _ + __ + ___
Out[21]: 6

Além disso, podemos nos referir à execuções específicas, usando a numeração que o IPython usa para diferenciar um par entrada-saída de outro. A sintaxe é bem simples: _ix, onde x é o número da entrada correspondente. Veja:

In [18]: 1
Out[18]: 1
In [19]: 2
Out[19]: 2
In [20]: 3
Out[20]: 3
In [21]: _ + __ + ___
Out[21]: 6
In [22]: print _i19 + 20
Out[22]: 22

Cool, huh?

Chamando o help de um objeto

Já falei sobre isso em um post anterior, mas veja de novo o uso do ponto de interrogação (?) para ver a documentação relacionada a determinado objeto:

In [31]: import math
In [32]: math.sqrt?
Type: builtin_function_or_method
String Form:<built-in function sqrt>
Docstring:
sqrt(x)
Return the square root of x.

Isso por si só já me faz usar o IPython ao invés do shell padrão.

As funções mágicas

O IPython é repleto de funções mágicas (magic functions) que fornecem enormes facilidades pro usuário. Elas são precedidas pelo caractere %. Vamos ver alguns exemplos.

Em um post anterior, falei sobre o módulo timeit que é usado para medir tempo de execução de programas Python. Existe uma função mágica pra quebrar esse galho pra gente. Por exemplo, se eu estiver na dúvida sobre qual trecho de código executaria de forma mais rápida, poderia fazer o seguinte:

In [35]: %%timeit sum = 0
 ...: for i in range(0, 10000):
 ...: sum += i
 ...: 
1000 loops, best of 3: 324 us per loop
In [36]: %%timeit sum = 0
 ...: for i in xrange(0, 10000):
 ...: sum += i
 ...: 
1000 loops, best of 3: 268 us per loop

Se o código a ser testado for de uma linha só, podemos usar %timeit (modo linha) ao invés de %%timeit (modo célula).

Outra função interessante é relacionada ao logging da sessão atual. %logstart faz com que a sessão atual passe a ser gravada em um arquivo .py com os comandos digitados dentro dele. %logon e %logoff servem para pausar e recomeçar o logging em uma sessão.

Executando comandos no sistema

Dentro de uma sessão IPython, podemos invocar comandos no sistema operacional usando o caractere !:

In[1]: !ls
 bin
 Desktop
 music
 pictures
 src
 videos
In[2]: !ps
 PID TTY TIME CMD
 25277 pts/0 00:00:00 bash
 25446 pts/0 00:00:00 ipython
 25458 pts/0 00:00:00 sh
 25459 pts/0 00:00:00 ps

Assim fica fácil interagir com o SO quando necessário for.

É isso. Se você tiver alguma outra dica interessante sobre o IPython, poste nos comentários.

virtualenv: ambientes virtuais para desenvolvimento

O post de hoje não será tão estreitamente relacionado à dicas sobre código Python como foram os anteriores. Ele irá tratar sobre o ambiente usado para o desenvolvimento em sua máquina.

Para quem está envolvido no desenvolvimento de vários projetos em paralelo, é bastante comum que um projeto tenha dependências de bibliotecas diferentes das usadas pelos outros projetos.
Em um ambiente Ubuntu Linux, por exemplo, os módulos Python instalados no sistema são armazenados em /usr/lib/python2.7/dist-packages/ (para Python 2.7). Dessa forma, se tivermos desenvolvendo dois projetos diferentes, eles estarão compartilhando algumas bibliotecas. E se for necessário que o projeto A utilize a versão x de determinado módulo, enquanto que o projeto B deve utilizar a versão y do mesmo módulo? Como os dois projetos, A e B, utilizam os módulos instalados no mesmo local do disco, fica difícil satisfazer esse requisito.

Outra situação muito comum de acontecer é estarmos desenvolvendo ou testando uma aplicação em um ambiente sobre o qual não temos permissões para a instalação de pacotes no sistema. Sabendo que muita gente passa por situações parecidas, foi criado o virtualenv. Se tivermos o virtualenv à disposição, podemos criar um ambiente virtual em nossa pasta pessoal e instalar os pacotes necessários dentro desse ambiente, sem a necessidade de ter privilégios de super-usuário. Quando for necessário lidar com vários projetos ao mesmo tempo, podemos criar um ambiente virtual para cada projeto, ambos na mesma máquina.

Assim, o virtualenv é uma ferramenta que permite que criemos, com o perdão da redundância, ambientes virtuais isolados para projetos Python. Por exemplo, se tivermos dois projetos, A e B, podemos criar dois ambientes virtuais, um para cada um dos projetos. Poderíamos chamá-los de venvA e venvB, por exemplo. Quando criamos esses dois ambientes, é criado um diretório com o nome de cada ambiente, com o seguinte conteúdo cada um:

bin  include  lib  local

Dentro do diretório bin, são criados arquivos binários (executáveis) necessários em um ambiente de desenvolvimento Python:

$ ls bin/
activate          activate.fish     easy_install    get_env_details
pip-2.7           postdeactivate    predeactivate   activate.csh
activate_this.py  easy_install-2.7  pip             postactivate
preactivate       python

Perceba que temos, dentre os arquivos listados, o interpretador Python (python), além de outras ferramentas importantes como o pip, que pode ser usadoo como instalador de pacotes do virtualenv. Existem também arquivos que são relacionados ao próprio ambiente virtual. Assim, cada ambiente virtual terá seus próprios executáveis para interpretar seus programas e gerenciar seus pacotes. Além disso, é criado também um diretório lib/python2.7/site-packages/, onde serão armazenados os pacotes que você instalar para aquele ambiente. Ou seja, ambos os ambientes venvA e venvB possuirão seu próprio interpretador Python, bem como suas próprias bibliotecas de código. Assim, cada projeto poderá ter versões específicas de determinados pacotes, sem a ocorrência de conflitos entre versões.

Como usar o virtualenv?

O virtualenv pode ser instalado de várias formas. A forma mais comum é através do gerenciador de pacotes pip. Tendo o pip instalado, você pode instalar o virtualenv com o seguinte comando:

user@host:~/$ sudo pip install virtualenv

Tendo feito isso, agora podemos começar a criar os ambientes virtuais para projetos Python. Primeiramente, vamos criar um ambiente:

user@host:~/$ virtualenv NomeDoAmbiente

Após executado o comando acima, será criado, no diretório atual, um subdiretório chamado NomeDoAmbiente, contendo aquela mesma estrutura já comentada anteriormente. Após o ambiente ter sido criado, precisamos ativá-lo:

user@host:~/$ source ./NomeDoAmbiente/bin/activate
(NomeDoAmbiente)user@host:~/$

Você irá perceber que o prompt do seu shell é alterado após a execução do comando acima, sendo a partir daí, precedido pelo nome do ambiente virtual ativo entre parênteses (veja acima). Isso faz também com que sua variável de ambiente $PATH passe a apontar, em primeiro lugar, para a pasta bin de dentro do ambiente virtual, de forma que quando você chamar o interpretador Python pela linha de comando, o executável que será aberto será o interpretador que está instalado dentro do ambiente virtual atual, pois será o primeiro encontrado no $PATH.

Instalando pacotes dentro do ambiente virtual

Uma vez que ativamos o ambiente virtual que desejamos usar, podemos então instalar os pacotes que forem necessários para nosso projeto. Por exemplo, considere que estamos trabalhando em nosso ambiente (ativado anteriormente), chamado de NomeDoAmbiente, e desejamos instalar o pacote Django. Podemos utilizar o gerenciador de pacotes pip que está instalado dentro de nosso ambiente virtual NomeDoAmbiente:

(NomeDoAmbiente)user@host:~/$ pip install Django
Downloading/unpacking Django
    Downloading Django-1.4.1.tar.gz (7.7Mb): 7.7Mb downloaded
    Running setup.py egg_info for package Django
Installing collected packages: Django
    Running setup.py install for Django
Successfully installed Django
Cleaning up...

Agora, podemos abrir um shell Python dentro do ambiente NomeDoAmbiente recém criado, e testar se o Django está mesmo instalado:

(NomeDoAmbiente)user@host:~/$ python
Python 2.7.2+ (default, Jul 20 2012, 22:15:08) 
[GCC 4.6.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import django
>>> django.__file__
'/home/user/NomeDoAmbiente/local/lib/python2.7/site-packages/django/__init__.pyc'

Tudo certo, o Django está instalado corretamente dentro do ambiente NomeDoAmbiente.

Para sair do ambiente virtual ativo, utilize o comando deactivate.

Gerando lista de dependências do projeto

Lembra quando você envia um projeto pronto para o chefe e ele manda um email dizendo que o projeto não funciona? Muitas vezes, o problema é que o computador do chefe não possui instaladas as bibliotecas que o projeto necessita. Nessa situação, a dupla virtualenv + pip nos ajuda novamente.

Uma vez que estejamos utilizando ambientes virtuais para nossos projetos, e que estejamos instalando todos os pacotes necessários via pip, temos facilmente em mãos a lista de pacotes dos quais nosso projeto depende. Para obter essa lista, basta utilizar o comando freeze do pip:

(NomeDoAmbiente)user@host:~/$ pip freeze
Django==1.4.1
Werkzeug==0.8.3
argparse==1.2.1
distribute==0.6.24
django-bootstrap-toolkit==2.5.8
django-extensions==0.9
django-registration==0.8
wsgiref==0.1.2

Tal comando escreve na saída-padrão a lista de pacotes (bem como suas versões), de cada uma das dependências instaladas via pip no projeto ativo. De posse dessa lista, podemos agora facilmente enviar a lista de dependências para o nosso chefe, utilizando as informações fornecidas pelo pip freeze para garantir que a máquina do chefe irá satisfazer todas as dependências do nosso projeto. Primeiro, devemos armazenar em um arquivo as informações geradas pelo pip freeze:

(NomeDoAmbiente)user@host:~/$ pip freeze > requirements.txt

Após isso, podemos enviar o arquivo requirements.txt para o chefão e, usando o pip, ele poderá executar:

(NomeDoAmbiente)anotheruser@anotherhost:~/$ pip install -r requirements.txt

O comando acima irá instalar as versões especificadas dos pacotes listados no arquivo fornecido como entrada. Tendo instalado corretamente os pacotes listados, nosso projeto estará com todas as dependências satisfeitas no computador do chefe, e poderá ser executado sem problemas.

virtualenvwrapper

Existe outro projeto, chamado virtualenvwrapper, que é um wrapper sobre o virtualenv, e que provê uma série de facilidades para a manipulação de ambientes virtuais. Vale muito a pena dar uma conferida nele!

Utilizando o virtualenvwrapper, a ativação de um ambiente fica muito mais simples:

user@host:~/$ workon NomeDoAmbiente
(NomeDoAmbiente)user@host:~/$

Além disso, ele provê vários atalhos para facilitar a nossa vida, como o cdvirtualenv, que troca o diretório atual para o diretório do virtualenv ativo. Alguns outros aliases úteis:

  • cdsitepackages: troca o diretório atual para o diretório onde os pacotes Python do ambiente virtual ativo estão instalados.
  • lssitepackages: comando muito útil para listarmos os arquivos/diretórios presentes no diretório de instalação dos módulos do ambiente virtual ativo.
  • mkvirtualenv NOME: cria um ambiente virtual chamado NOME.
  • dentre outros 😉

virtualenv embutido no Python 3.3

A versão 3.3 do Python traz consigo a possibilidade de criarmos ambientes virtuais sem a necessidade de instalação do pacote virtualenv separadamente, ou seja, o virtualenv fará parte da distribuição oficial do Python. Mais informações podem ser encontradas na documentação oficial: http://docs.python.org/dev/library/venv.html.

Enfim…

O virtualenv é extremamente útil quando você está trabalhando com vários projetos ao mesmo tempo, ou em um ambiente sobre o qual você não tenha permissões de super-usuário. Mas fique atento, pois o virtualenv irá instalar uma versão de cada biblioteca e dos executáveis para cada um dos seus ambientes virtuais, o que irá consumir mais espaço em disco.

Customizando o IPython

Dias atrás estive tentando descobrir como trocar o prompt-padrão do IPython [1]. Para quem não sabe, o prompt-padrão de comandos do IPython é:

In [x]:

Onde x é um contador de entradas fornecidos pelo usuário. O que eu queria era substituir tal prompt pelo prompt padrão do shell Python:

>>>

Para isso, é preciso antes criar um perfil de configurações de usuário para o IPython, com o comando (em um shell Linux):

$ ipython profile create

Assim, será criado um diretório com as configurações do IPython em seu diretório de usuário, onde está armazenado o arquivo de configurações ipython_config.py (no meu caso está em ~/.config/ipython/profile_default/ipython_config.py).

Para substituir o prompt do IPython, procure pela linha com o seguinte conteúdo dentro do arquivo de configurações e descomente-a:

# c.PromptManager.in_template = 'In [\\#]: '

Após descomentar tal linha, substitua o valor ‘In [\\#]: ‘ por ‘>>> ‘, para que tal linha fique como a linha abaixo:

c.PromptManager.in_template = '>>> '

Uma coisa que acho irritante é o IPython sempre pedindo confirmação quando desejo fechá-lo, após ter pressionado ^-d. Para evitar que ele pergunte se você deseja mesmo fechá-lo, basta descomentar a seguinte linha no mesmo arquivo e trocar o valor True para False:

# c.TerminalInteractiveShell.confirm_exit = True

A linha deverá ficar assim:

c.TerminalInteractiveShell.confirm_exit = False

Além dessas, existem muitas coisas que podem ser personalizadas no IPython. Você pode vê-las comentadas no arquivo supracitado. Para personalizar outros aspectos relacionados ao prompt de comandos, vá até a seção “PromptManager configuration” do arquivo e altere de acordo com o seu gosto.

[1] http://ipython.org

Por que __name__ == “__main__” ?

Já viu algum programa escrito em Python, que lá pelo final tem um trecho de código parecido com o código abaixo?

if __name__ == "__main__":
    # faça algo

Quem não conhece, deve estar se perguntando: que condição é essa? O que é __name__? O que é “__main__”?

Para entender isso, nada melhor que a prática. Faça o seguinte:

  • Usando seu editor de textos favorito, crie um arquivo .py (por exemplo: teste.py);
  • Dentro desse arquivo, coloque o seguinte código:

print __name__

OK, criamos um programa/módulo python chamado teste. Isso quer dizer que podemos executá-lo pela linha de comando, ou importá-lo em um shell python. Agora vamos executá-lo como um programa:


user@host:~/ $ python teste.py

__main__

Repare na saída que o programa gerou: __main__. Esse é o nome interno que todo programa/módulo Python recebe quando executado como um programa pela linha de comando.

Agora, abra um shell Python no mesmo diretório onde o arquivo teste.py foi gravado e importe tal módulo:

Python 2.7.2+ (default, Oct 4 2011, 20:06:09)
[GCC 4.6.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import teste
teste
>>>

Repare que agora, a variável __name__ foi impressa com um valor diferente: teste, que é o nome que demos ao nosso programa. Assim, o teste __name__ == “__main__” está verificando nada mais do que se o código do módulo está sendo executado como um programa, tendo sido chamado pela linha de comando, ou sendo importado como um módulo. Mas, pra que serve isso?

Vamos a outro exemplo. Vamos implementar um módulo com algumas funções que achamos úteis. Vamos chamar esse módulo como utilidades.py.

import sys

def erro(msg):
    print "Erro:", msg
    sys.exit(1)

def inc(x):
    return x + 1

def dec(x):
    return x - 1

def quadrado(x):
    return x**2

Mas, enquanto vamos implementando, queremos fazer alguns testes para saber se o código funciona como esperamos, então complementamos o código acima com uns testes ao final:

import sys
def erro(msg):
    print "Erro:", msg
    sys.exit(1)

def inc(x):
    return x + 1

def dec(x):
    return x - 1

def quadrado(x):
    return x**2

print inc(10) # deve mostrar 11
print dec(10) # deve mostrar 9
print quadrado(5) # deve mostrar 25

Perfeito, se executarmos o código acima pela linha de comando, teremos o resultado que esperamos:

user@host:~/ $ python utilidades.py
11
9
25

Até aí, tudo certo. Mas, e se precisarmos de uma dessas funções e importarmos esse módulo (utilidades) em algum outro programa ou até mesmo em um shell Python? Vamos ver:

Python 2.7.2+ (default, Oct 4 2011, 20:06:09)
[GCC 4.6.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import utilidades
11
9
25
>>>

Opa! “Mas eu queria apenas usar as funções que o módulo utilidades disponibiliza, não ver esses números na tela!”. Pois é. O problema é que as três linhas de código que finalizam o módulo estão sendo executadas de forma incondicional, não importando se o programa estiver sendo executado pela linha de comando ou sendo importado em outro programa. Podemos resolver esse problema adicionando o teste __name__ == “__main__”:

import sys

def erro(msg):
    print "Erro:", msg
    sys.exit(1)

def inc(x):
    return x + 1

def dec(x):
    return x - 1

def quadrado(x):
    return x**2

if __name__ == "__main__":
    print inc(10)
    print dec(10)
    print quadrado(5)
Agora, o comportamento do programa será diferente quando executado pela linha de comando (quando o __name__ for igual a string “__main__”), do que quando for importado como módulo.