Até agora, nos trabalhamos com o console interativo ou um arquivo temporário de bloco de código. Com o objetivo de trabalhar com funções ou instruções pré-definidas que podem ser aproveitadas em diversas partes do código ou em diversos tipos de códigos, iremos organizar nossa codificação em arquivos conhecidos como script ou módulos.

Utilizando o Spyder2 mesmo, podemos abrir um novo bloco de código e salvá-lo como um arquivo .py.

Scripts

Vamos escrever um script, que é simplesmente um arquivo .py com uma sequencia de instruções que serão executadas toda vez que o script for chamado. Escreve as seguintes instruções em um arquivo chamado teste.py e salve na sua área de trabalho.

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

mensagem = "Executando um script"
for palavra in mensagem.split():
    print palavra

[/pastacode]

Agora, execute o script interativamente, dentro do console interativo. Para isso, utilize o seguinte comando:

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

runfile(r'CaminhoParaAreaDeTrabalho\teste.py')

[/pastacode]

Se desejar definir o diretório de trabalho do script, execute:

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

runfile(r'CaminhoParaAreaDeTrabalho\teste.py', wdir=r'CaminhoParaAreaDeTrabalho\Desktop')

[/pastacode]

Sendo que o CaminhoParaAreaDeTrabalho é o caminho para a sua área de trabalho, como por exemplo, /home/usuario/desktop no linux ou c:\Users\usuario\Desktop no windows (usuário é seu nome de usuário no seu sistema operacional). O script foi executado. Como foi executado no console interativo, as variáveis definidas no script agora estão disponíveis no namespace do interpretador. Também é possível executar um script como um programa, executando o script dentro de um terminal (Linux/Mac) ou do prompt de comando (cmd no windows). Por exemplo, abra um terminal do Linux ou um cmd no windows, navegue até a sua área de trabalho e digite:

[pastacode lang=”c” message=”” highlight=”” provider=”manual”]

python teste.py

[/pastacode]

Observe que o script será executado. No windows somente irá funcionar se o python estiver no Path das variáveis de ambiente. Scripts também aceitam argumentos na linha de comando. Por exemplo, escreva as seguintes linhas no  arquivo teste2.py (salve na área de trabalho também):

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

import sys
print sys.argv

a = sys.argv[1]

mensagem = "Executando um script"
for palavra in mensagem.split():
    print palavra, int(a)*2

[/pastacode]

Agora no terminal (Linux/Mac) ou no cmd (windows) digite:

[pastacode lang=”c” message=”” highlight=”” provider=”manual”]

python teste2.py 5

[/pastacode]

Sendo que 5 é o argumento que passamos para nosso script teste2.py. O argumento sempre é um string de uma lista do sys.argv.

Importando objetos de módulos

Execute os seguinte comandos no console interativo:

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

import os
os
os.listdir('.')

[/pastacode]

Observe que são listados os arquivos do corrente diretório de trabalho. É possível renomear o nome do módulo importado para a utilização:

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

import os as outroNome
outroNome.listdir('.')

[/pastacode]

O método listdir importado do módulo os pode ser importado também na forma:

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

from os import listdir

[/pastacode]

A diferença é que o primeiro tipo de importação importa todos os métodos do módulo os, o segundo somente o método listdir. Ainda é possível utilizar a seguinte sintaxe:

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

from os import *

[/pastacode]

ATENÇÃO: essa forma de importar é conhecida como importação estrela. USE COM CAUTELA.

  • Torna o código difícil de ler e entender: de onde vem os símbolos?
  • Torna impossível de adivinhar a funcionalidade pelo contexto e pelo nome (os.name é o nome do os), e de tirar proveito do autocompletar.
  • Restringe os nomes das variáveis que você pode usar: os.name pode sobrescrever o nome ou vice-versa.
  • Cria possíveis conflitos de nomes entre os módulos.
  • Torna o código impossível de ser checado estaticamente por símbolos indefinidos.

Módulos são uma ótima forma de organizar o código de forma hierárquica. Na verdade, todos as ferramentas de computação científica  que iremos utilizar são módulos. Quem utiliza o Python(x,y) no windows tem esses módulos automaticamente carregados ao iniciar o spyder. Digite scientific no console interativo para ver como são feitas essas importações. Para os usuários de Linux e Mac, se os módulos estiverem disponíveis, o Spyder2 também os importa. Digitem scientific no console interativo para mais informações.

Criando Módulos

Se desejarmos escrever programas grandes e bem organizados (comparando com scripts simples), onde alguns objetos são definidos (variáveis, funções, classes) onde seja possível reutilizar esses objetos várias vezes, precisamos criar nossos próprios módulos. Vamos criar um módulo chamado teste contido no arquivo teste.py. Abra um novo arquivo no spyder2, insira o código abaixo e salve como teste.py no mesmo diretório que está sendo executado o arquivo corrente no console interativo.

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

"Um módulo de teste."

def print_b():
    "Imprima b."
    print 'b'

def print_a():
    "Imprima a."
    print 'a'

c = 2
d = 2

[/pastacode]

Nesse arquivo foram definidas duas funções print_a e print_b. Suponha que se deseja chamar a função print_a a partir do console interativo. É possível executar o arquivo como um script, mas como somente queremos acesso à função print_a, precisamos importar ele como um módulo. A sintaxe é a seguinte, digite no console interativo:

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

import teste

teste.print_a()

teste.print_b()

[/pastacode]

O arquivo teste deve estar no mesmo diretório que está sendo executado o console interativo para poder ser importado como módulo. Importando o módulo nos dá acesso aos seus objetos utilizando a sintaxe modulo.objeto. Não esqueça de colocar o nome do módulo antes do nome do objeto, do contrário o Python não irá reconhecer a instrução. Observe que ao se digitar o nome do módulo teste com o ponto, o spyder2 já oferece uma lista dos métodos disponíveis para utilização e ao se escolher um dos métodos, o object inspector já apresenta a descrição (desde que tenha se utilizado as docstrings na função). Também é possível importar os objetos para o namespace principal, como já feito anteriormente:

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

from teste import print_a, print_b

[/pastacode]

E digite no console interativo:

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

print_a()

[/pastacode]

ATENÇÃO: Cache do módulo. Se você modificar o teste.py você precisa recarregar o módulo ou obterá os resultados antigos.

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

reload(teste)

[/pastacode]

‘__main__’ e carregamento de módulos

Crie o arquivo teste2.py com o seguinte código:

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

import sys

def print_a():
    "Imprime a."
    print 'a'

print sys.argv[0] #imprime o nome do script

if __name__ == '__main__':
    print_a()

[/pastacode]

Importando:

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

import teste2

[/pastacode]

Executando:

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

runfile(r'teste.py')

[/pastacode]

Scripts ou Módulos? Como organizar o código?

Regra:

  • Conjuntos de instruções que são chamados diversas vezes devem ser escritos como funções;
  • Funções que são chamadas por diversos scripts devem ser escritas em um módulo, e então somente o módulo é importado nos diferentes scripts (nunca copie e cole as funções em todos os scripts!!!).

Como importar um módulo de um diretório remoto?

Existem diversas soluções, dependendo principalmente do seus sistema operacional. Quando a declaração import seumodulo é executada, o módulo seumodulo é vasculhado em certa lista dada de diretórios. Essa lista inclui o caminho padrão da installação do Python (por exemplo no linux, /usr/lib/python) assim como a lista dos diretórios especificados pela variável de ambiente PYTHONPATH (ou PATH no windows). A lista pode ser acessada pelo comando sys.path.

Módulos devem estar nesses diretórios ou no diretório do arquivo principal do código em questão, de forma que você possa:

  • escrever seus próprios módulos dentro de diretórios já definidos nos diretórios padrões (por exemplo, os módulos instalados no python no linux ficam em: /usr/local/lib/python2.6/dist-packages);
  • modificar a variável de ambiente PYTHONPATH (ou PATH no windows) para incluir mais diretórios que contenham os seus módulos;
  • ou ainda modificar a variável sys.path com um script python:

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

import sys
novo_caminho = '/home/usuario/meus_modulos'
if novo_caminho not in sys.path:
    sys.path.append(novo_caminho)

[/pastacode]

Esse método não é muito robusto, por fazer o código menos portável (diretório pré-definido do usuário) e por fazer com que você tenha que adicionar o diretório ao seu sys.path toda vez que desejar importar um módulo daquele diretório.

Veja  http://docs.python.org/tutorial/modules.html para mais informações sobre os módulos.

Pacotes

Um pacote é um diretório que contém diversos módulos. Um pacote também é um módulo que contém submódulos, que por sua vez podem ter seus próprios submódulos, etc. Um arquivo especial chamado __init__.py, que não precisa possuir nenhum código, podendo ser vazio, diz ao Python que tal diretório que o contenha é um pacote do Python, do qual módulos podem ser importados.

Por exemplo, vamos ver o pacote do scipy, digite no console interativo:

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

import scipy
scipy.__file__

import scipy.version
scipy.version.version

from scipy.ndimage import morphology
morphology.binary_dilation() #observe o object inspector ao digitar os parenteses

[/pastacode]

Boas práticas

Indentação é obrigatória em Python! Todo bloco de comando após dois pontos possui um nível de indentação em relação à linha anterior. A indentação deve ser utilizada após def  f(): ou while:, por exemplo, obrigatoriamente, e o final dos blocos é marcado por outro código iniciando na primeira coluna, sem nenhum nível de indentação (caso tenha sido utilizado apenas uma indentação no bloco de código anterior).

Seguir a risca as regras de indentação é um preço a pagar para se livrar de caracteres como { e ; que delimitam blocos lógicos em outras linguagens. Indentações incorretas levam a erro na execução do código.

No início é um pouco complexo lembrar da indentação, mas com o uso e a ajuda do spyder2, logo acostuma-se com a ideia e até percebe-se que o código fica bem mais limpo, organizado e fácil de ler.

Dentro do spyder2 já é predefinido o tamanho da indentação em uma tabulação (tecla tab) ou 4 espaços. Uma boa prática é sempre utilizar uma tabulação (um tab) como padrão para as indentações.

Uma outra boa prática é evitar linhas muito longas. Se você possuir um grande número de dados para uma variável, como por exemplo, uma string long, utilize uma quebra de linha para deixar tudo sempre visível sem precisar rolar a barra de rolagem horizontal.

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

linha_longa = "Essa é uma linha que seria muito longa e saíria da tela \
quebrada em duas."

print linha_longa

[/pastacode]

Use espaços para um código bem escritos, coloque após vírgulas, no entorno de operadores aritméticos, etc.

[pastacode lang=”python” message=”” highlight=”” provider=”manual”]

a=3*b-3 #empacotado
a = 3*b-3 #melhor apresentado

[/pastacode]

Um certo número de regras para se escrever códigos apresentáveis, e o mais importante, utilização da mesma convenção que todo mundo, é mostrada no Style Guide for Python Code.

Por fim, lembre-se, utilize nomes de objetos que significam alguma coisa.