Importação de Módulos em Python

Pode-se utilizar duas maneiras distintas para importação de módulos em Python, são elas: import e from. Basicamente, provêem as mesmas funcionalidades, só que, com algumas pequenas diferenças:

  • import: a instrução import traz o módulo como um todo. Tal característica faz com que seja preciso qualificar um atributo em sua busca.
  • from: a instrução from realiza uma cópia de nomes de um módulo não necessitando de qualificar um atributo.

Nota: Tome o módulo employee.py como parâmetro para o restante da postagem. Tal módulo contém apenas duas funções sem nenhuma funcionalidade real.

# !/usr/bin/env python

# MODULE: employee -> file module reponsible for tasks to employees
# AUTHOR: Jose Mauro da Silva Sandy - http://informacaocomdiversao.blogspot.com
#
# CONTACT: jmsandy_at_gmail_dot_com
#
# DATE: 2008-12-26
#
# This is a fictitious example.
# The correct way to implement this module would be using class.
###############################################################################

# Arguments 1. percentage increase
#           2. salary
# result    wage hike
#
def salary_inc(perc=0, salary=0):
   return (salary + ((salary / 100) * perc))

# Arguments 1. list employee
# result    sum of number of employee
#
def sum_emp(list_emp=[]):
   return len(list_emp)
Instruções: import vs. from

Import

Quando importado, o módulo employee.py, passa a ser uma variável no script que o importa. Como apresentado, a instrução import traz um módulo como um todo, logo precisa-se utilizar o módulo importado para qualificar seus atributos.

import employee
print employee.salary_inc(10, 1500), " - ", employee.sum_emp()
Note que foi necessário fornecer o nome do módulo importado para se obter acesso as funções(atributos) e que com essa simples importação obteve-se ingresso a TODOS os seus atributos.

from e from *

Ao contrário do import, a instrução from copia nomes de um arquivo de módulo. Devido a isso não é necessário informar o nome do módulo que foi importado.

from employee import salary_inc
print salary_inc(10, 1500)
Observe que o único atributo importado pela instrução from, foi salary_inc, logo não será possível ter acesso a nenhum outro atributo do módulo. Para conseguir ingresso aos demais atributos torna-se indispensável utilizar a instrução from *, como abaixo:
from employee import *
print salary_inc(10, 1500), " - ", sum_emp()

Nota: Caso haja a curiosidade de executar o print usado no primeiro exemplo(import) em from omitindo o objeto importado, verá que acontecerá um erro em tempo de execução, pois o interpretador não encontrará a variável sum_emp().
Detalhes importantes na construção de módulos

Antes que qualquer atributo presente em um módulo possa ser acessado, o mesmo deve ter sido importado por uma das instruções acima citadas. É importante ressaltar, que para um arquivo ser importado é preciso que o módulo esteje no caminho de pesquisa e também possua a extensão .py, pois todos os arquivos com extensão diferente ou ausente são desconsiderados, causando assim erro de execução.

Uma vez carregado, os módulos em execução não sofrem nenhum mudança a menos que sejam recarregados. Tal episódio não reflete muito a realidade e fica apenas a termo de conceituação. Para recarregar um módulo é preciso que este tenha sido carregado previamente com sucesso, usa-se a função interna reload(module) para realizar esse processo. Este recarregamento trabalha de forma diferente para as instruções import e from. Em import, todas as mudanças alteradas são refletidas imediatamente em todos os clientes que importem o módulo, já na instrução from, os clientes não serão atingidos pois tal instrução trabalha com cópias para os atributos do módulo.

José Mauro da Silva Sandy


Referências

  • MARK, Lutz. ASCHER, David. Aprendendo Python. Tradução João Tortello. 2. ed. Porto Alegre : Bookman, 2007.
Série Módulos em Python
Leia Também


13 comentários:

  Lopes

27 de dezembro de 2008 às 14:38

Salve, simpatia!

Texto esclarecedor, cara, mas como sou chato, quero chamar a atenção para alguns detalhes:

1. No exemplo employee.py, o excesso de comentários prejudica o entendimento. Se você reparar, há 25 linhas, sendo que apenas 4 delas são de código. Não vejo necessidade do cabeçalho e dos comentários de uso dos métodos, uma vez que poderiam ser explicados no texto.

2. Verifique a indentação. Já percebi que o editor do Blogger come as minhas indentações. Parece que fez o mesmo com as suas!

3. Segundo o PEP8, não deve haver espaço entre o parâmetro, o sinal de atribuição e o valor, na passagem de parâmetros de uma função: def foo(p=1, v='1'). Sacou?!

3. Não mude o caso de palavras reservadas no texto, mesmo que seja início de uma frase. Assim, o título From e from * deveria ser from e from *.

4. Eu trocaria o nome da séria para Módulos em Python. O nome atual parece abrangente demais.

5. Interessante notar que este atributo aqui não é o mesmo das classes, por mais que lááá no fundo possam ser a mesma coisa: identificadores.

6. Li no PEP8 algo sobre a utilização da variável __all__ com módulos. Se bem me lembro, ela é uma lista com o nome de cada atributo que seria importado com o from *. Assim, o desenvolvedor do módulo poderia esconder alguns métodos. Isso confere? Você pretende falar disso em outras postagens?!

Apesar disso, o texto está bom! Eu que sou chato mesmo! ;-)

Abraço!

  José Mauro

28 de dezembro de 2008 às 08:37

Fala brow!

Kra todos as funções ou qualquer outra instrução que se refere a uma variavel e um atributo. Lembre-se que toda definição cria-se um objeto, logo na importação acessariamos os atributos deste objeto.

Esse negócio do texto comendo a identação da foda. Quanto aos comentários embora nesse caso torna-se desnecessário, penso que comentário nunca é demais. Ao meu ver quem for pegar e usar a sua função precisa saber dos argumentos e seu valor de retorno, mas em Python seria melhor usar docstring, isso foi um vacilo.

Não sou a variável __all___ vai ser abordada, essa sua pergunta vai ser respondida pela próxima postagem que está para sair.

Abraço brow, eh nois.

  Lopes

28 de dezembro de 2008 às 15:15

Salve!

Não quis dizer pra abolir todos os comentários. As explicações das funções podem ficar no texto em vez de no código. De qualquer forma, o maior problema é o cabeçalho. Eu prefiro colocá-lo apenas em funções que eu desenvolvi e estou disponibilizando no blog, em exemplos não. Vale notar ainda, que a primeira linha está sem o sinal de exclamação após o sustenido. O certo seria: #!/usr/bin/env python. ;-)

Sobre os atributos, concordo. Como eu disse, lá no fundo eles podem ser quase a mesma coisa que variáveis. Contudo, você falar em atributos no escopo de OO é uma coisa. Já em módulos é outra. A OO tem premissas que transcendem módulos, como, principalmente, neste caso, encapsulamento. A idéia de chamar os identificadores, no escopo de módulos, de variáveis, visa não confundir a cabeça de quem lê. Nos cursos de programação, inclusive, aprende-se assim. Identificadores em um programa são variáveis, procedimentos, funções etc. Identificadores em uma classe são atributos, métodos, construtores etc.

[]!

  José Mauro

28 de dezembro de 2008 às 15:47

Fala Zé!!!

Valeu pela dica quanto a exclamação, realmente passei batido.

Olha, para mim, a melhor forma de trata-los são como atributos.

Realizar o tratamento deles como identificadores não condiz com o que realmente eles são. Dentro de um arquivo de nível superior podemos chama-los de identificadores, mas para todos os arquivos que os importam passam a ser atributos que no momento da importação você instancia um objeto e passa a ter acesso aos seus atributos.

E ao meu ver são muito semelhantes a classes.

Abraço.

  Lopes

28 de dezembro de 2008 às 16:09

Bom, cada um na sua...

Mas não seria tratá-los como identificadores, mas sim como variáveis, como aprendemos nos cursos de programação.

São parecidos com classes, sim. Mas não são classes. Talvez, justamente pelo fato de serem parecidos, é que seria interessante diferenciá-los.

Uma classe é um aglomerado de características e comportamentos de um conjunto de objetos. Um módulo pode conter suas variáveis globais, funções e classes implementados. Um módulo pode servir como um contêiner de classes, mas não pode ser instanciado e não há regras que impessam o desenvolvedor de esconder ou mostrar suas variáveis ou funções ou classes. Já para a classe, o encapsulamento dita que os atributos só podem ser acessíveis diretamente, por dentro dela, jamais por fora (apesar de Python subverter isso).

A idéia de eu ter tocado neste assunto, é que não aprendemos a chamar variáveis de atributos. Na verdade, só vamos conhecer atributos em OO. Da mesma forma, aprendemos, incialmente, procedimentos e funções e não métodos. Pegue qualquer apostila ou livro de programação e você verá, na programação estruturada, variáveis, funções e procedimentos. Em OO, você verá atributos, construtores e métodos.

Creio que você entenda a diferença entre as notações. Mas muita gente pode não saber ou, mesmo que saiba, pode se confundir. Um módulo possui variáveis. Uma classe possui atributos. No fundo, pode ser a mesma coisa. Mas, da mesma forma que carro é carro e moto é moto, apesar dos dois serem meios de transporte com rodas, variável é variável e atributo é atributo, apesar de serem ponteiros para uma região de memória com um valor. E módulo é módulo e classe é classe. Por mais semelhança que tenham, são diferentes.

[]!

  José Mauro

28 de dezembro de 2008 às 16:44

Com certeza, cada um com seu ponto de vista, isso é legal.

Realmente módulos não é um classe. Mais quando importado, um simples módulo, passa a ser um objeto, então passar a ter as mesmas características, esse é o meu ver.

Tratar no arquivo de nível superior nomes como variáveis ou identificadores é uma coisa, agora quando importados passam a ser objetos.

A respeito do encapsulamento tem-se __all__ que importada somente os atributos que você quer exportar com o seu módulo, sem contar que com a sintaxe _atributo, a instrução from não importa tais atributos.

Não é a mesma coisa que classe, isso é fato, mas chamar de variável para mim não encaixa muito no contexto amplo de módulo.

Mais é isso ai, cada um com sua opinião. O que seria do seu corinthias se todos(como eu) torcesse pelo São Paulo. kkkkk

abraço brow.

  Lopes

28 de dezembro de 2008 às 17:35

Vira essa boca pra lá...

A grande questão que eu estou levantando é a seguinte: cada um pode chamar qualquer coisa do que quiser. Se eu começar a falar blá e blé, ninguém vai entender. Assim eles vão me perguntar e eu vou ter que explicar que blá é casa e blé praia.

Você pode, no seu entendimento, chamar uma variável de que qualquer coisa, inclusive atributo. Só que, eventualmente, uma pessoa não vai entender isso. Pior do que não entender, a pessoa pode confundir isso com classe e te interpretar errado, achando que você está trocando os termos.

Não se encontra na literatura (pelo menos eu nunca vi), que uma variável de módulo é um atributo. Também nunca vi alguém falar dessa forma. A questão é usar os nomes, de acordo com o que aprendemos e não criar notações novas, incompatíveis com o que encontramos nos livros.

Se você seguir a sua nomenclatura, um módulo tem atributos, uma classe tem atributos, métodos da classe tem atributos, funções tem atributos... Então, ao explicar isso, você terá que discriminar, atributo do módulo, da classe, da função, do método...

A bandeira que eu defendo, portanto, é: aprendemos assim, os grandes nomes escrevem assim, outras pessoas usam esses conceitos. Não devemos mudar por mudar. É possível criar encapsulamento com módulos em python, usando __all__ e underscore? Parabéns pro time de Python, mas não existe um guia que diz que as variáveis do módulo precisem estar escondidas dos outros módulos. Em contrapartida, para classes, existe a OO que dita isso. A mesma OO, que diz que uma variável, dentro da classe, chama-se a atributo e que funções da classe chamam-se métodos. Enquanto não criarem algo como a OO para módulos, os termos que valem são os já existentes.

Ainda não criaram um nome especial para variáveis de módulos, então eu aconselho e uso o nome variável em módulos. Exite a OO e seus conceitos, por isso eu uso atributo em classes.

No passado recente, você mesmo trocou as bolas num dos meus artigos, por entender que os atributos da classe que eu implementei fossem usados como as variáveis de módulos.

Já existem estas notações. Porque criar novas?! ;-)

[]!

  Lopes

28 de dezembro de 2008 às 17:50

Esqueci de comentar isso:

"Realmente módulos não é um classe. Mais quando importado, um simples módulo, passa a ser um objeto, então passar a ter as mesmas características, esse é o meu ver."

Se isso fosse verdade, não se usaria import e from para instanciar módulos. Também não é usual (e nem sei se há como) ter mais de uma instância de um módulo num programa, ao mesmo tempo. Este fato já mostra que há diferenciação entre os dois termos. Se um módulo, mesmo instanciado, fosse tão flexível quanto uma classe, não existiria a classe.

Módulos existem para agrupar variáveis, funções e classes que possuírem a mesma semântica. Classes existem para agrupar características de grupos de objetos. Os escopos são diferenes. Enxergar uma classe num módulo pode ser interessante apenas a nível de comparação, para entendimento dos termos.

  José Mauro

28 de dezembro de 2008 às 18:05

Olha eu entendo da seguinte forma:
1ª Situação: um módulo também pode ser um arquivo de nível superior, logo suas funções, classes e variáveis, seriam no contexto amplo variáveis do módulo.

2ª Situação: Quando importamos esse módulo, por exemplo, um módulo chamado m.py, este módulo vira um objeto m em seu arquivo de nível superior e todas as suas variáveis internas serão tratadas como atributos pelo arquivo que o importou. Veja que acessamos m.atributo, não é a mesma coisa quanto utilizamos classe?

É claro que tem a questão de polimorfismo, sobrecarga, construtor, métodos, etc. Tudo isso em classe, mas para mim o termo correto é atributos do módulo.

É possível sim ocultar variáveis(neste contexto é variável porque está na parte interna do módulo) a serem exportadas pelo módulo, irei abortar isso na próxima postagem. Nada impede que você utilize seu arquivo de módulo como um arquivo de nível superior e devido a isso pode ser do seu interessante ocultar alguns nomes utilizados.

Kra não to criando nenhuma notação, um módulo importado para suas variáveis como atributos para o arquivo que os importa.

Abraço.

  José Mauro

28 de dezembro de 2008 às 18:09

Respondendo a continuação de seu comentário, pelo desprendimento de tempo um módulo é importado somente uma vez em tempo de execução.

E você pode importar quanto módulos quiser.

Para alterar as caracteristicas do módulo importado é preciso chamar a função reload(modulo) para que o módulo seja atualizado.

Detalhe isso funciona somente com a instrução import porque trabalha por referência. Módulos importados com a instrução from não funciona o reload porque trabalha-se com cópias.

  Lopes

28 de dezembro de 2008 às 18:29

Sim, sim, sim, sa-la-bim!

Eu sei que podemos encapsular variáveis em módulos. O que eu questionei é que não há um guia de boa conduta que nos diga que devemos fazer isso. Nas classes, nós fazemos, por que existe a OO.

Eu concordo que, uma vez importado, um método torna-se similar a uma classe instanciada. Contudo, sabemos que ele não é uma classe, portanto não tem atributos. Tem variáveis.

O próprio guia do Python 2.6 define um módulo como coleção de variáveis e funções...

Creio que uma abordagem apropriada seria comparar módulo com classe, dizendo que, se na classe você faz objeto.atributo ou objeto.método, no módulo você faz modulo.variavel ou modulo.funcao.

Note que voltamos àquilo que eu disse: uma cadeira e uma mesa têm muitas similaridades. Ambas podem servir para apoiar objetos ou para sentar, mas convencionou-se que cadeira é cadeira e mesa é mesa. Se você troca os nomes, por mais que você saiba o que está fazendo, não pode cobrar que os outros entendam. E você mesmo pode se enrolar.

Como eu disse, ainda não vi um livro escrito por um nome de peso ou largamente adotado que diz que módulos têm variáveis que tornam-se atributos quando usados. Por isso, uso e recomendo que todos usem os nomes que aprendemos, que nossos professores ensinaram e que estão nos livros.

Veja o guia de módulos do Python 2.6, onde dizem que módulos têm variáveis e funções:
http://docs.python.org/tutorial/modules.html

Abraço!

PS: Não tô dizendo que o seu entendimento do assunto está errado. É só com relação à exposição dos termos. :-)

  Lopes

28 de dezembro de 2008 às 18:36

Respondendo ao comentário solto:

O que eu quis dizer é que não é usual fazer:

import os as o
import os as j

Já em classes, sim:

c1 = Clock()
c2 = Clock()

;-)

  José Mauro

28 de dezembro de 2008 às 18:43

Kra pelo que você me conhece você sabe que eu vou morrer com essa notação na cabeça. Pode até ser confuso mas pra mim é mais claro, e é o correto.

Mais eu não estipulei isso. No livro que sigo, Aprendendo Python(O'Reilly), é uma editora respeitada, aborda dessa forma e eu concordo plenamente com os autores, ai é questão de interpretação. Qualquer dia desses de mostro o livro.

Respondendo o outro comentário.

Com certeza não é usual para caminhos pequenos, mas torna muito útil para pacote de módulos. Isso será abortado mais adiante.

Abraço.