Como descarregar (recarregar) um módulo?


797

Eu tenho um servidor Python de execução demorada e gostaria de poder atualizar um serviço sem reiniciar o servidor. Qual é a melhor maneira de fazer isso?

if foo.py has changed:
    unimport foo  <-- How do I do this?
    import foo
    myfoo = foo.Foo()

53
Lembrete: "importar" não significa "carregar", significa "carregar se ainda não estiver carregado e depois importar para o espaço de nome".
Kos

3
a questão não deve incluir 'descarregar', como isso não é possível em python ainda - recarga é no entanto um paradigma conhecido como respondidas abaixo
robertmoggach

Eu tive o mesmo problema ao usar um módulo dinâmico no aplicativo py2exe. Como o py2exe sempre mantém o bytecode no recarregamento do diretório zip não estava funcionando. Mas eu encontrei uma solução funcional usando o módulo import_file. Agora meu aplicativo está funcionando bem.
Pritam Pan

2
E se você quiser "descarregar" porque a tentativa de excluir um arquivo .pyc está sendo usada pelo código?
darkgaze

Respostas:


793

Você pode recarregar um módulo quando ele já tiver sido importado usando a reloadfunção incorporada (somente Python 3.4+) :

from importlib import reload  
import foo

while True:
    # Do some things.
    if is_changed(foo):
        foo = reload(foo)

No Python 3, reloadfoi movido para o impmódulo. Em 3.4, impfoi preterido em favor de importlibe reloadfoi adicionado a este último. Ao direcionar 3 ou mais recente, faça referência ao módulo apropriado ao chamá reload-lo ou importá-lo.

Eu acho que é isso que você quer. Servidores da Web como o servidor de desenvolvimento do Django usam isso para que você possa ver os efeitos das alterações no seu código sem reiniciar o processo do servidor.

Para citar os documentos:

O código dos módulos Python é recompilado e o código no nível do módulo reexecutado, definindo um novo conjunto de objetos vinculados a nomes no dicionário do módulo. A função init dos módulos de extensão não é chamada uma segunda vez. Como em todos os outros objetos em Python, os objetos antigos são recuperados somente depois que suas contagens de referência caem para zero. Os nomes no espaço para nome do módulo são atualizados para apontar para qualquer objeto novo ou alterado. Outras referências aos objetos antigos (como nomes externos ao módulo) não são recuperadas para se referir aos novos objetos e devem ser atualizadas em cada espaço de nome em que ocorrem, se desejado.

Como você observou na sua pergunta, você precisará reconstruir Fooobjetos se a Fooclasse residir no foomódulo.


10
na verdade, os Django dev próprio servidor é reiniciado quando você altera um arquivo .. (ele reinicia o servidor, não apenas recarrega o módulo)
Hasen

25
De onde vem essa função "is_changed"? não vejo documentação nele e ele não roda no meu ambiente Python 3.1.3, nem no 2.6.4.
jedmao

5
não cdleary, Django não pode apenas usar recarga: pyunit.sourceforge.net/notes/reloading.html
raylu

14
@BartoszKP se Xnão for um módulo, você podeimport sys; reload(sys.modules[X.__module__])
drevicko 16/04

5
@jedmao @JamesDraper Tenho certeza de que a is_changedfunção é apenas uma função arbitrária que você precisaria escrever; não é um built-in. Por exemplo, ele poderia abrir o arquivo correspondente ao módulo que você está importando e diferenciá-lo com uma versão em cache para verificar se ele foi alterado.
James Mchugh

252

No Python 3.0-3.3, você usaria: imp.reload(module)

O BDFL tem respondido a esta pergunta.

No entanto, impfoi preterido no 3.4, a favor deimportlib (obrigado @Stefan! ).

Eu acho que , portanto, você usaria agora importlib.reload(module), embora não tenha certeza.


23
O novato sério é grato a aprender sobre nuances críticas entre Python 2 e 3.
Smandoli

24
imp.reload (imp) é válido?
Loïc Faure-Lacroix

2
@ LoïcFaure-Lacroix da mesma forma reload(__builtins__)é válida em 2.x
JBernardo

1
@ Tarrasch: é o módulo Python que você deseja recarregar, como no exemplo da pergunta.
Paul D. Waite

3
@ LoïcFaure-Lacroix sim, o imp pode se recarregar.
precisa

92

Pode ser especialmente difícil excluir um módulo se não for um Python puro.

Aqui estão algumas informações de: Como eu realmente excluo um módulo importado?

Você pode usar sys.getrefcount () para descobrir o número real de referências.

>>> import sys, empty, os
>>> sys.getrefcount(sys)
9
>>> sys.getrefcount(os)
6
>>> sys.getrefcount(empty)
3

Números maiores que 3 indicam que será difícil se livrar do módulo. O módulo caseiro "vazio" (sem nada) deve ser coletado como lixo após

>>> del sys.modules["empty"]
>>> del empty

como a terceira referência é um artefato da função getrefcount ().


4
Acabei de descobrir que, se o módulo faz parte de um pacote, você também deve excluí-lo:setattr(package, "empty", None)
u0b34a0f6ae

6
Esta é a solução correta, especialmente se você tiver um pacote com módulos aninhados. reload()apenas recarrega o módulo superior, e qualquer coisa dentro dele não será recarregada, a menos que você o exclua primeiro do sys.modules.
Cerin

73

reload(module), mas somente se for completamente independente. Se qualquer outra coisa tiver uma referência ao módulo (ou qualquer objeto pertencente ao módulo), você receberá erros sutis e curiosos causados ​​pelo código antigo por mais tempo do que o esperado e coisas como isinstancenão funcionar em versões diferentes do mesmo código.

Se você tiver dependências unidirecionais, também deverá recarregar todos os módulos que dependem do módulo recarregado para se livrar de todas as referências ao código antigo. E, em seguida, recarregue os módulos que dependem dos módulos recarregados, recursivamente.

Se você tiver dependências circulares, o que é muito comum, por exemplo, ao lidar com o recarregamento de um pacote, você deve descarregar todos os módulos do grupo de uma só vez. Não é possível fazer isso reload()porque ele reimporta cada módulo antes que suas dependências sejam atualizadas, permitindo que referências antigas entrem em novos módulos.

A única maneira de fazer isso nesse caso é hackear sys.modules, o que é meio que sem suporte. Você precisaria passar e excluir cada sys.modulesentrada que desejava recarregar na próxima importação e também excluir entradas cujos valores devem Nonelidar com um problema de implementação relacionado ao armazenamento em cache de importações relativas com falha. Não é muito agradável, mas contanto que você tenha um conjunto totalmente independente de dependências que não deixa referências fora de sua base de código, é viável.

Provavelmente é melhor reiniciar o servidor. :-)


1
O dreload não é especificamente para esse cenário?
Josh

@ Josh: não, é para recarregar uma árvore de pacotes, e mesmo assim funciona apenas desde que o pacote não tenha dependências externas / circulares.
bobince

1
Você pode elaborar a peça com Nonevalores porque estou enfrentando exatamente esse problema: estou excluindo itens de sys.modulese depois da reimportação de algumas dependências importadas None.
22413 schlamar

@shclamar: Veja stackoverflow.com/questions/1958417/… (e os links de lá) para obter mais informações. Não está claro para mim (mesmo olhando para o código import.c) como as Noneentradas conseguiram retornar ao mecanismo de importação quando as entradas 'reais' foram excluídas, e não consigo fazer isso acontecer no 2.7; no futuro, certamente não será mais um problema, pois as importações relativas implícitas desapareceram. Enquanto isso, excluir todas as entradas com Nonevalor parece corrigi-lo.
21913

1
@Eliethesaiyan: você quer dizer a reloadfunção? Está embutido, você não precisa importar nenhuma biblioteca.
bobince

63
if 'myModule' in sys.modules:  
    del sys.modules["myModule"]

3
+1. Meu objetivo era executar testes de nariz no python. Depois que eu tinha carregado um módulo e renomeado algumas funções, os nomes antigos permaneceu ao chamar nose.run(), mesmo depoisreload(my_module) %run my_module
Peter D

5
Se o seu módulo importa seus próprios submódulos, você pode precisar excluí-los também. Algo como [del(sys.modules[mod] for mod in sys.modules.keys() if mod.startswith('myModule.')].
drevicko

Eu não acho que isso descarrega o módulo. No Python 3.8: import sys; import json; del sys.modules['json']; print(json.dumps([1]))e o módulo json ainda está funcionando, embora não esteja mais no sys.modules.
Seperman

60

Para Python 2, use a função interna reload () :

reload(module)

Para Python 2 e 3.2–3.3, use reload from module imp :

import imp
imp.reload(module)

Mas imp está obsoleto desde a versão 3.4 em favor do importlib , então use:

import importlib
importlib.reload(module)

ou

from importlib import reload
reload(module)

2
para lidar com qualquer um destes casos: from six import reload_module(necessidade de pip install sixprimeira, claro)
Anentropic

@Anentropic: É um bom conselho recomendar o uso de seis pacotes, mas a sintaxe é from six.moves import reload_module( doc )
x0s

23

O código a seguir permite compatibilidade com Python 2/3:

try:
    reload
except NameError:
    # Python 3
    from imp import reload

Você pode usá-lo como reload()nas duas versões, o que simplifica as coisas.


18

A resposta aceita não trata do caso Y de importação de X. Este código lida com ele e também com o caso de importação padrão:

def importOrReload(module_name, *names):
    import sys

    if module_name in sys.modules:
        reload(sys.modules[module_name])
    else:
        __import__(module_name, fromlist=names)

    for name in names:
        globals()[name] = getattr(sys.modules[module_name], name)

# use instead of: from dfly_parser import parseMessages
importOrReload("dfly_parser", "parseMessages")

No caso de recarregamento, reatribuímos os nomes de nível superior aos valores armazenados no módulo recém-recarregado, que os atualiza.


Percebeu um problema, globals () se refere ao módulo em que você define essa função; portanto, se você o definir em um módulo diferente daquele em que você o chama, não funcionará.
Joseph Garvin

Para interativa, após >>> from X import Ya recarga fazer>>> __import__('X', fromlist='Y')
Bob Stein

@ BobStein-VisiBone, existe uma maneira de fazer isso funcionar quando fromlist='*'?
28615 Mike C

Boa pergunta, não sei @MikeC. A propósito, estou tendendo a interromper quase todo o uso fromnas declarações de importação. Apenas import <package>package.symbol explícito e explícito no código. Perceba que isso nem sempre é possível ou desejável. (Aqui está uma exceção: a partir print_function futura importação.)
Bob Stein

Mike C: o que funciona para mim éfoo = reload(foo); from foo import *
rampion 19/10/16

16

Esta é a maneira moderna de recarregar um módulo:

from importlib import reload

Se você deseja oferecer suporte a versões do Python anteriores à 3.5, tente o seguinte:

from sys import version_info
if version_info[0] < 3:
    pass # Python 2 has built in reload
elif version_info[0] == 3 and version_info[1] <= 4:
    from imp import reload # Python 3.0 - 3.4 
else:
    from importlib import reload # Python 3.5+

Para usá-lo, execute reload(MODULE), substituindo MODULEpelo módulo que você deseja recarregar.

Por exemplo, reload(math)recarregará o mathmódulo.


4
Ou apenas faça from importlib import reload. Então você pode fazer reload(MODULE_NAME). Não há necessidade dessa função.
pault 02/02

Eu acredito que modulereload(MODULE_NAME)é mais auto-explicativo do que justo reload(MODULE_NAME)e tem uma chance menor de entrar em conflito com outras funções.
Richie Bendall

@RichieBendall Desculpe, mas esta resposta está completamente errada. A função reload () pega o objeto do módulo, não o nome do módulo ... Leia os documentos: docs.python.org/3/library/importlib.html#importlib.reload E eu concordo com @ pault - esse "como modulereload" é ​​supérfluo .
Mdevpl #

Mudei minha resposta para refletir sua opinião.
precisa saber é o seguinte

13

Se você não está em um servidor, mas está desenvolvendo e precisa recarregar frequentemente um módulo, aqui está uma boa dica.

Primeiro, verifique se você está usando o excelente shell IPython , do projeto Jupyter Notebook. Depois de instalar o Jupyter, você pode iniciá-lo com ipython, ou jupyter console, melhor ainda, com jupyter qtconsoleum bom console colorido com conclusão de código em qualquer sistema operacional.

Agora no seu shell, digite:

%load_ext autoreload
%autoreload 2

Agora, toda vez que você executar seu script, seus módulos serão recarregados.

Além do 2, existem outras opções da magia de carregamento automático :

%autoreload
Reload all modules (except those excluded by %aimport) automatically now.

%autoreload 0
Disable automatic reloading.

%autoreload 1
Reload all modules imported with %aimport every time before executing the Python code typed.

%autoreload 2
Reload all modules (except those excluded by %aimport) every time before
executing the Python code typed.

7

Para aqueles como eu que querem descarregar todos os módulos (quando executados no interpretador Python no Emacs ):

   for mod in sys.modules.values():
      reload(mod)

Mais informações estão em Recarregando módulos Python .


Na verdade, isso não parece funcionar de maneira confiável (na versão 2.6), porque nem tudo sys.modules.values()é um módulo. Por exemplo: >>> type (sys.modules.values ​​() [1]) <class 'email.LazyImporter'> Então, se eu tentar executar esse código, ele cai (Eu sei que não é uma solução prática, apenas apontando isso).
Francis Davey

Nem funciona em pitões anteriores - como está escrito. Eu tive que excluir alguns nomes. Atualizarei a postagem quando mover esse código para o meu novo computador.

2
Funciona bem no Python 2.7 após algumas modificações:if mod and mod.__name__ != "__main__": imp.reload(mod)
Czarek Tomczak

2
Isso funciona bem para mim: import imp [recarregar (m) para m em sys.modules.values ​​() se m e não " " em m .__ nome e não imp.is_builtin (m .__ nome__)]
Patrick Wolf

5

O Enthought Traits possui um módulo que funciona razoavelmente bem para isso. https://traits.readthedocs.org/en/4.3.0/_modules/traits/util/refresh.html

Ele recarregará qualquer módulo que foi alterado e atualizará outros módulos e objetos instanciados que o estão usando. Ele não funciona na maioria das vezes com __very_private__métodos e pode engasgar com a herança de classe, mas poupa muito tempo de reiniciar o aplicativo host ao escrever guis do PyQt, ou coisas que são executadas em programas como o Maya ou o Nuke. Talvez não funcione entre 20 e 30% do tempo, mas ainda é incrivelmente útil.

O pacote da Enthought não recarrega os arquivos no momento em que eles mudam - você precisa chamá-lo explicitamente - mas isso não deve ser tão difícil de implementar se você realmente precisar


5

Aqueles que estão usando o python 3 e recarregam a partir do importlib.

Se você tiver problemas como parece que o módulo não é recarregado ... Isso ocorre porque ele precisa de algum tempo para recompilar o pyc (até 60 segundos).



3

Outra opção. Veja que o padrão do Python importlib.reloadapenas reimporta a biblioteca passada como argumento. Ele não recarregará as bibliotecas importadas pela sua lib. Se você alterou muitos arquivos e possui um pacote um pouco complexo para importar, é necessário fazer uma atualização profunda .

Se você possui o IPython ou o Jupyter instalado, pode usar uma função para recarregar profundamente todas as bibliotecas:

from IPython.lib.deepreload import reload as dreload
dreload(foo)

Se você não possui o Jupyter, instale-o com este comando no seu shell:

pip3 install jupyter

Tanto o dreload Ipython quanto o reload () do importlib se queixam reload() argument must be module. Estou usando uma importação de função personalizada e parece não funcionar. O uso de módulos internos funciona. :-( que é um desperdício de tempo sendo recarregar ipython para cada pequena mudança que eu fiz para o meu código ...
m3nda

2

Editar (Resposta V2)

A solução anterior é boa apenas para obter as informações de redefinição, mas não altera todas as referências (mais do que reloadmas menos que o necessário). Para definir todas as referências também, tive que entrar no coletor de lixo e reescrever as referências lá. Agora isso trabalha como charme!

Observe que isso não funcionará se o GC estiver desligado ou se estiver recarregando dados que não são monitorados pelo GC. Se você não quiser mexer com o GC, a resposta original pode ser suficiente para você.

Novo Código:

import importlib
import inspect
import gc
from weakref import ref


def reset_module(module, inner_modules_also=True):
    """
    This function is a stronger form of importlib's `reload` function. What it does, is that aside from reloading a
    module, it goes to the old instance of the module, and sets all the (not read-only) attributes, functions and classes
    to be the reloaded-module's
    :param module: The module to reload (module reference, not the name)
    :param inner_modules_also: Whether to treat ths module as a package as well, and reload all the modules within it.
    """

    # For the case when the module is actually a package
    if inner_modules_also:
        submods = {submod for _, submod in inspect.getmembers(module)
                   if (type(submod).__name__ == 'module') and (submod.__package__.startswith(module.__name__))}
        for submod in submods:
            reset_module(submod, True)

    # First, log all the references before reloading (because some references may be changed by the reload operation).
    module_tree = _get_tree_references_to_reset_recursively(module, module.__name__)

    new_module = importlib.reload(module)
    _reset_item_recursively(module, module_tree, new_module)


def _update_referrers(item, new_item):
    refs = gc.get_referrers(item)

    weak_ref_item = ref(item)
    for coll in refs:
        if type(coll) == dict:
            enumerator = coll.keys()
        elif type(coll) == list:
            enumerator = range(len(coll))
        else:
            continue

        for key in enumerator:

            if weak_ref_item() is None:
                # No refs are left in the GC
                return

            if coll[key] is weak_ref_item():
                coll[key] = new_item

def _get_tree_references_to_reset_recursively(item, module_name, grayed_out_item_ids = None):
    if grayed_out_item_ids is None:
        grayed_out_item_ids = set()

    item_tree = dict()
    attr_names = set(dir(item)) - _readonly_attrs
    for sub_item_name in attr_names:

        sub_item = getattr(item, sub_item_name)
        item_tree[sub_item_name] = [sub_item, None]

        try:
            # Will work for classes and functions defined in that module.
            mod_name = sub_item.__module__
        except AttributeError:
            mod_name = None

        # If this item was defined within this module, deep-reset
        if (mod_name is None) or (mod_name != module_name) or (id(sub_item) in grayed_out_item_ids) \
                or isinstance(sub_item, EnumMeta):
            continue

        grayed_out_item_ids.add(id(sub_item))
        item_tree[sub_item_name][1] = \
            _get_tree_references_to_reset_recursively(sub_item, module_name, grayed_out_item_ids)

    return item_tree


def _reset_item_recursively(item, item_subtree, new_item):

    # Set children first so we don't lose the current references.
    if item_subtree is not None:
        for sub_item_name, (sub_item, sub_item_tree) in item_subtree.items():

            try:
                new_sub_item = getattr(new_item, sub_item_name)
            except AttributeError:
                # The item doesn't exist in the reloaded module. Ignore.
                continue

            try:
                # Set the item
                _reset_item_recursively(sub_item, sub_item_tree, new_sub_item)
            except Exception as ex:
                pass

    _update_referrers(item, new_item)

Resposta original

Conforme escrito na resposta de @ bobince, se já houver uma referência a esse módulo em outro módulo (especialmente se ele foi importado com a aspalavra - chave like import numpy as np), essa instância não será substituída.

Isso me mostrou bastante problemático ao aplicar testes que exigiam um estado "clean-slate" dos módulos de configuração, por isso escrevi uma função denominada reset_moduleque usa importliba reloadfunção de e substitui recursivamente todos os atributos do módulo declarado. Foi testado com o Python versão 3.6.

import importlib
import inspect
from enum import EnumMeta

_readonly_attrs = {'__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__',
               '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__func__', '__ge__', '__get__',
               '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__init_subclass__',
               '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__',
               '__reduce__', '__reduce_ex__', '__repr__', '__self__', '__setattr__', '__sizeof__', '__str__',
               '__subclasshook__', '__weakref__', '__members__', '__mro__', '__itemsize__', '__isabstractmethod__',
               '__basicsize__', '__base__'}


def reset_module(module, inner_modules_also=True):
    """
    This function is a stronger form of importlib's `reload` function. What it does, is that aside from reloading a
    module, it goes to the old instance of the module, and sets all the (not read-only) attributes, functions and classes
    to be the reloaded-module's
    :param module: The module to reload (module reference, not the name)
    :param inner_modules_also: Whether to treat ths module as a package as well, and reload all the modules within it.
    """

    new_module = importlib.reload(module)

    reset_items = set()

    # For the case when the module is actually a package
    if inner_modules_also:
        submods = {submod for _, submod in inspect.getmembers(module)
                   if (type(submod).__name__ == 'module') and (submod.__package__.startswith(module.__name__))}
        for submod in submods:
            reset_module(submod, True)

    _reset_item_recursively(module, new_module, module.__name__, reset_items)


def _reset_item_recursively(item, new_item, module_name, reset_items=None):
    if reset_items is None:
        reset_items = set()

    attr_names = set(dir(item)) - _readonly_attrs

    for sitem_name in attr_names:

        sitem = getattr(item, sitem_name)
        new_sitem = getattr(new_item, sitem_name)

        try:
            # Set the item
            setattr(item, sitem_name, new_sitem)

            try:
                # Will work for classes and functions defined in that module.
                mod_name = sitem.__module__
            except AttributeError:
                mod_name = None

            # If this item was defined within this module, deep-reset
            if (mod_name is None) or (mod_name != module_name) or (id(sitem) in reset_items) \
                    or isinstance(sitem, EnumMeta):  # Deal with enums
                continue

            reset_items.add(id(sitem))
            _reset_item_recursively(sitem, new_sitem, module_name, reset_items)
        except Exception as ex:
            raise Exception(sitem_name) from ex

Nota: Use com cuidado! O uso desses módulos em módulos não periféricos (módulos que definem classes usadas externamente, por exemplo) pode levar a problemas internos no Python (como problemas de decapagem / não decapagem).


1

para mim, no caso de Abaqus, é assim que funciona. Imagine que seu arquivo é Class_VerticesEdges.py

sys.path.append('D:\...\My Pythons')
if 'Class_VerticesEdges' in sys.modules:  
    del sys.modules['Class_VerticesEdges']
    print 'old module Class_VerticesEdges deleted'
from Class_VerticesEdges import *
reload(sys.modules['Class_VerticesEdges'])

Esta resposta é uma cópia direta daqui: ebanshi.cc/questions/1942/…
SiHa

0

Eu tive muitos problemas ao tentar recarregar algo dentro do Sublime Text, mas finalmente pude escrever esse utilitário para recarregar os módulos no Sublime Text com base no código sublime_plugin.pyusado para recarregar os módulos.

Isso abaixo permite que você recarregue módulos de caminhos com espaços em seus nomes; depois, depois de recarregar, você pode apenas importar como costuma fazer.

def reload_module(full_module_name):
    """
        Assuming the folder `full_module_name` is a folder inside some
        folder on the python sys.path, for example, sys.path as `C:/`, and
        you are inside the folder `C:/Path With Spaces` on the file 
        `C:/Path With Spaces/main.py` and want to re-import some files on
        the folder `C:/Path With Spaces/tests`

        @param full_module_name   the relative full path to the module file
                                  you want to reload from a folder on the
                                  python `sys.path`
    """
    import imp
    import sys
    import importlib

    if full_module_name in sys.modules:
        module_object = sys.modules[full_module_name]
        module_object = imp.reload( module_object )

    else:
        importlib.import_module( full_module_name )

def run_tests():
    print( "\n\n" )
    reload_module( "Path With Spaces.tests.semantic_linefeed_unit_tests" )
    reload_module( "Path With Spaces.tests.semantic_linefeed_manual_tests" )

    from .tests import semantic_linefeed_unit_tests
    from .tests import semantic_linefeed_manual_tests

    semantic_linefeed_unit_tests.run_unit_tests()
    semantic_linefeed_manual_tests.run_manual_tests()

if __name__ == "__main__":
    run_tests()

Se você executar pela primeira vez, isso deverá carregar o módulo, mas se mais tarde você puder novamente o método / função, run_tests()ele recarregará os arquivos de teste. Com o Sublime Text ( Python 3.3.6), isso acontece muito porque o intérprete nunca fecha (a menos que você reinicie o Sublime Text, ou seja, o Python3.3intérprete).


-1

Outra maneira poderia ser importar o módulo em uma função. Dessa forma, quando a função é concluída, o módulo recebe o lixo coletado.


4
O módulo nunca coletará lixo porque uma referência global é mantida pelo menos em sys.modules.
Todos os trabalhadores têm Essencial
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.