Como posso carregar um módulo Python devido ao seu caminho completo? Observe que o arquivo pode estar em qualquer lugar do sistema de arquivos, pois é uma opção de configuração.
Como posso carregar um módulo Python devido ao seu caminho completo? Observe que o arquivo pode estar em qualquer lugar do sistema de arquivos, pois é uma opção de configuração.
Respostas:
Para o Python 3.5+, use:
import importlib.util
spec = importlib.util.spec_from_file_location("module.name", "/path/to/file.py")
foo = importlib.util.module_from_spec(spec)
spec.loader.exec_module(foo)
foo.MyClass()
Para Python 3.3 e 3.4, use:
from importlib.machinery import SourceFileLoader
foo = SourceFileLoader("module.name", "/path/to/file.py").load_module()
foo.MyClass()
(Embora isso tenha sido descontinuado no Python 3.4.)
Para Python 2, use:
import imp
foo = imp.load_source('module.name', '/path/to/file.py')
foo.MyClass()
Existem funções de conveniência equivalentes para arquivos e DLLs Python compilados.
Veja também http://bugs.python.org/issue21436 .
__import__
.
imp.load_source
define apenas .__name__
o módulo retornado. isso não afeta o carregamento.
imp.load_source()
determina a chave da nova entrada criada no sys.modules
dicionário; portanto, o primeiro argumento realmente afeta o carregamento.
imp
módulo está obsoleto desde a versão 3.4: O imp
pacote está com obsoleta pendente em favor de importlib
.
A vantagem de adicionar um caminho ao sys.path (sobre o uso de imp) é que ele simplifica as coisas ao importar mais de um módulo de um único pacote. Por exemplo:
import sys
# the mock-0.3.1 dir contains testcase.py, testutils.py & mock.py
sys.path.append('/foo/bar/mock-0.3.1')
from testcase import TestCase
from testutils import RunTests
from mock import Mock, sentinel, patch
sys.path.append
para apontar para um único arquivo python em vez de um diretório?
importlib.import_module(mod_name)
pode ser usado em vez da importação explícita aqui, se o nome do módulo não for conhecido em tempo de execução, eu adicionaria um sys.path.pop()
no final, assumindo que o código importado não tente importar mais módulos à medida que é usado.
Se o seu módulo de nível superior não for um arquivo, mas estiver empacotado como um diretório com __init__.py, a solução aceita quase funcionará, mas não completamente. No Python 3.5+, o seguinte código é necessário (observe a linha adicionada que começa com 'sys.modules'):
MODULE_PATH = "/path/to/your/module/__init__.py"
MODULE_NAME = "mymodule"
import importlib
import sys
spec = importlib.util.spec_from_file_location(MODULE_NAME, MODULE_PATH)
module = importlib.util.module_from_spec(spec)
sys.modules[spec.name] = module
spec.loader.exec_module(module)
Sem essa linha, quando exec_module é executado, ele tenta vincular importações relativas no seu nível superior __init__.py ao nome do módulo de nível superior - nesse caso "mymodule". Mas "mymodule" ainda não foi carregado, então você receberá o erro "SystemError: Módulo pai 'mymodule' não carregado, não pode executar importação relativa". Então, você precisa vincular o nome antes de carregá-lo. A razão para isso é a invariante fundamental do sistema de importação relativo: "A retenção invariável é que, se você tiver sys.modules ['spam'] e sys.modules ['spam.foo'] (como faria após a importação acima ), o último deve aparecer como o atributo foo do primeiro ", conforme discutido aqui .
mymodule
?
/path/to/your/module/
é realmente /path/to/your/PACKAGE/
? e mymodule
você quer dizer myfile.py
?
Para importar seu módulo, você precisa adicionar seu diretório à variável de ambiente, temporária ou permanentemente.
import sys
sys.path.append("/path/to/my/modules/")
import my_module
Adicionando a seguinte linha ao seu .bashrc
arquivo (no linux) e execute source ~/.bashrc
no terminal:
export PYTHONPATH="${PYTHONPATH}:/path/to/my/modules/"
Crédito / Fonte: saarrrr , outra questão de stackexchange
Parece que você não deseja importar especificamente o arquivo de configuração (que tem muitos efeitos colaterais e complicações adicionais envolvidas), apenas deseja executá-lo e acessar o espaço de nome resultante. A biblioteca padrão fornece uma API especificamente para isso na forma de runpy.run_path :
from runpy import run_path
settings = run_path("/path/to/file.py")
Essa interface está disponível no Python 2.7 e Python 3.2 ou superior
result[name]
, result.get('name', default_value)
, etc)
from runpy import run_path; from argparse import Namespace; mod = Namespace(**run_path('path/to/file.py'))
Você também pode fazer algo assim e adicionar o diretório em que o arquivo de configuração está localizado no caminho de carregamento do Python e, em seguida, fazer uma importação normal, supondo que você saiba o nome do arquivo com antecedência, neste caso "config".
Confuso, mas funciona.
configfile = '~/config.py'
import os
import sys
sys.path.append(os.path.dirname(os.path.expanduser(configfile)))
import config
imp.load_dynamic(module_name, path_to_file)
para DLLs
def import_file(full_path_to_module):
try:
import os
module_dir, module_file = os.path.split(full_path_to_module)
module_name, module_ext = os.path.splitext(module_file)
save_cwd = os.getcwd()
os.chdir(module_dir)
module_obj = __import__(module_name)
module_obj.__file__ = full_path_to_module
globals()[module_name] = module_obj
os.chdir(save_cwd)
except:
raise ImportError
import_file('/home/somebody/somemodule.py')
except:
cláusula abrangente raramente é uma boa ideia.
save_cwd = os.getcwd()
try: …
finally: os.chdir(save_cwd)
this is already addressed by the standard library
sim, mas o python tem o hábito desagradável de não ser compatível com versões anteriores ... como a resposta verificada diz que existem duas maneiras diferentes antes e depois do 3.3. Nesse caso, eu gostaria de escrever minha própria função universal do que verificar a versão em tempo real. E sim, talvez esse código não esteja muito bem protegido por erros, mas mostra uma ideia (que é os.chdir (), ainda não pensei nisso), com base na qual posso escrever um código melhor. Portanto, +1.
Aqui está um código que funciona em todas as versões do Python, de 2.7 a 3.5 e provavelmente até outras.
config_file = "/tmp/config.py"
with open(config_file) as f:
code = compile(f.read(), config_file, 'exec')
exec(code, globals(), locals())
Eu testei. Pode ser feio, mas até agora é o único que funciona em todas as versões.
load_source
não funcionou porque importa o script e fornece ao script acesso aos módulos e globais no momento da importação.
Eu vim com uma versão ligeiramente modificada da maravilhosa resposta de @ SebastianRittau (para Python> 3.4, eu acho), que permitirá que você carregue um arquivo com qualquer extensão como módulo usando, em spec_from_loader
vez de spec_from_file_location
:
from importlib.util import spec_from_loader, module_from_spec
from importlib.machinery import SourceFileLoader
spec = spec_from_loader("module.name", SourceFileLoader("module.name", "/path/to/file.py"))
mod = module_from_spec(spec)
spec.loader.exec_module(mod)
A vantagem de codificar o caminho de forma explícita SourceFileLoader
é que o mecanismo não tentará descobrir o tipo do arquivo a partir da extensão. Isso significa que você pode carregar algo como um .txt
arquivo usando este método, mas você não poderia fazê-lo com spec_from_file_location
sem especificar o carregador, porque .txt
não está na importlib.machinery.SOURCE_SUFFIXES
.
Você quer dizer carregar ou importar?
Você pode manipular a sys.path
lista, especificar o caminho para o seu módulo e depois importá-lo. Por exemplo, dado um módulo em:
/foo/bar.py
Você poderia fazer:
import sys
sys.path[0:0] = ['/foo'] # puts the /foo directory at the start of your path
import bar
sys.path[0:0] = ['/foo']
Explicit is better than implicit.
Então, por que não em sys.path.insert(0, ...)
vez de sys.path[0:0]
?
Eu acredito que você pode usar imp.find_module()
e imp.load_module()
carregar o módulo especificado. Você precisará dividir o nome do módulo fora do caminho, ou seja, se você deseja carregar, /home/mypath/mymodule.py
precisará fazer:
imp.find_module('mymodule', '/home/mypath/')
... mas isso deve fazer o trabalho.
Você pode usar o pkgutil
módulo (especificamente o walk_packages
método) para obter uma lista dos pacotes no diretório atual. A partir daí, é trivial usar o importlib
maquinário para importar os módulos que você deseja:
import pkgutil
import importlib
packages = pkgutil.walk_packages(path='.')
for importer, name, is_package in packages:
mod = importlib.import_module(name)
# do whatever you want with module now, it's been imported!
Criar módulo python test.py
import sys
sys.path.append("<project-path>/lib/")
from tes1 import Client1
from tes2 import Client2
import tes3
Criar módulo python test_check.py
from test import Client1
from test import Client2
from test import test3
Podemos importar o módulo importado do módulo.
Esta área do Python 3.4 parece ser extremamente tortuosa de entender! No entanto, com um pouco de hacking usando o código de Chris Calloway como um começo, consegui fazer algo funcionar. Aqui está a função básica.
def import_module_from_file(full_path_to_module):
"""
Import a module given the full path/filename of the .py file
Python 3.4
"""
module = None
try:
# Get module name and path from full path
module_dir, module_file = os.path.split(full_path_to_module)
module_name, module_ext = os.path.splitext(module_file)
# Get module "spec" from filename
spec = importlib.util.spec_from_file_location(module_name,full_path_to_module)
module = spec.loader.load_module()
except Exception as ec:
# Simple error printing
# Insert "sophisticated" stuff here
print(ec)
finally:
return module
Parece usar módulos não obsoletos do Python 3.4. Não pretendo entender o porquê, mas parece funcionar de dentro de um programa. Eu achei a solução de Chris funcionada na linha de comando, mas não de dentro de um programa.
Não estou dizendo que é melhor, mas por uma questão de completude, eu queria sugerir a exec
função, disponível nos python 2 e 3., que
exec
permite executar código arbitrário no escopo global ou interno, fornecido como um dicionário.
Por exemplo, se você tiver um módulo armazenado em "/path/to/module
"com a função foo()
, poderá executá-lo da seguinte maneira:
module = dict()
with open("/path/to/module") as f:
exec(f.read(), module)
module['foo']()
Isso torna um pouco mais explícito que você esteja carregando o código dinamicamente e concede a você poder adicional, como a capacidade de fornecer recursos personalizados.
E se o acesso por meio de atributos, em vez de chaves, é importante para você, você pode criar uma classe de dict personalizada para os globais, que fornece esse acesso, por exemplo:
class MyModuleClass(dict):
def __getattr__(self, name):
return self.__getitem__(name)
Para importar um módulo de um determinado nome de arquivo, você pode estender temporariamente o caminho e restaurar o caminho do sistema na referência finalmente ao bloco :
filename = "directory/module.py"
directory, module_name = os.path.split(filename)
module_name = os.path.splitext(module_name)[0]
path = list(sys.path)
sys.path.insert(0, directory)
try:
module = __import__(module_name)
finally:
sys.path[:] = path # restore
Se tivermos scripts no mesmo projeto, mas em diferentes diretórios, podemos resolver esse problema pelo seguinte método.
Nesta situação utils.py
está emsrc/main/util/
import sys
sys.path.append('./')
import src.main.util.utils
#or
from src.main.util.utils import json_converter # json_converter is example method
Isso deve funcionar
path = os.path.join('./path/to/folder/with/py/files', '*.py')
for infile in glob.glob(path):
basename = os.path.basename(infile)
basename_without_extension = basename[:-3]
# http://docs.python.org/library/imp.html?highlight=imp#module-imp
imp.load_source(basename_without_extension, infile)
name, ext = os.path.splitext(os.path.basename(infile))
. Seu método funciona porque a restrição anterior à extensão .py. Além disso, você provavelmente deve importar o módulo para alguma entrada de variável / dicionário.
Eu fiz um pacote que usa imp
para você. Eu chamo import_file
e é assim que é usado:
>>>from import_file import import_file
>>>mylib = import_file('c:\\mylib.py')
>>>another = import_file('relative_subdir/another.py')
Você pode obtê-lo em:
http://pypi.python.org/pypi/import_file
ou em
Importar módulos de pacote em tempo de execução (receita Python)
http://code.activestate.com/recipes/223972/
###################
## #
## classloader.py #
## #
###################
import sys, types
def _get_mod(modulePath):
try:
aMod = sys.modules[modulePath]
if not isinstance(aMod, types.ModuleType):
raise KeyError
except KeyError:
# The last [''] is very important!
aMod = __import__(modulePath, globals(), locals(), [''])
sys.modules[modulePath] = aMod
return aMod
def _get_func(fullFuncName):
"""Retrieve a function object from a full dotted-package name."""
# Parse out the path, module, and function
lastDot = fullFuncName.rfind(u".")
funcName = fullFuncName[lastDot + 1:]
modPath = fullFuncName[:lastDot]
aMod = _get_mod(modPath)
aFunc = getattr(aMod, funcName)
# Assert that the function is a *callable* attribute.
assert callable(aFunc), u"%s is not callable." % fullFuncName
# Return a reference to the function itself,
# not the results of the function.
return aFunc
def _get_class(fullClassName, parentClass=None):
"""Load a module and retrieve a class (NOT an instance).
If the parentClass is supplied, className must be of parentClass
or a subclass of parentClass (or None is returned).
"""
aClass = _get_func(fullClassName)
# Assert that the class is a subclass of parentClass.
if parentClass is not None:
if not issubclass(aClass, parentClass):
raise TypeError(u"%s is not a subclass of %s" %
(fullClassName, parentClass))
# Return a reference to the class itself, not an instantiated object.
return aClass
######################
## Usage ##
######################
class StorageManager: pass
class StorageManagerMySQL(StorageManager): pass
def storage_object(aFullClassName, allOptions={}):
aStoreClass = _get_class(aFullClassName, StorageManager)
return aStoreClass(allOptions)
No Linux, adicionar um link simbólico no diretório em que seu script python está localizado funciona.
ou seja:
ln -s /absolute/path/to/module/module.py /absolute/path/to/script/module.py
O python criará /absolute/path/to/script/module.pyc
e atualizará se você alterar o conteúdo de/absolute/path/to/module/module.py
inclua o seguinte em mypythonscript.py
from module import *
git
e verificando o seu git status
para verificar se suas alterações no script estão realmente retornando ao documento de origem e não se perdendo no éter.
Eu escrevi minha própria função de importação global e portátil, com base no importlib
módulo, para:
sys.path
de um armazenamento de caminho de pesquisa que nunca.A estrutura de diretório de exemplos:
<root>
|
+- test.py
|
+- testlib.py
|
+- /std1
| |
| +- testlib.std1.py
|
+- /std2
| |
| +- testlib.std2.py
|
+- /std3
|
+- testlib.std3.py
Dependência e ordem de inclusão:
test.py
-> testlib.py
-> testlib.std1.py
-> testlib.std2.py
-> testlib.std3.py
Implementação:
Armazenamento das últimas alterações: https://sourceforge.net/p/tacklelib/tacklelib/HEAD/tree/trunk/python/tacklelib/tacklelib.py
test.py :
import os, sys, inspect, copy
SOURCE_FILE = os.path.abspath(inspect.getsourcefile(lambda:0)).replace('\\','/')
SOURCE_DIR = os.path.dirname(SOURCE_FILE)
print("test::SOURCE_FILE: ", SOURCE_FILE)
# portable import to the global space
sys.path.append(TACKLELIB_ROOT) # TACKLELIB_ROOT - path to the library directory
import tacklelib as tkl
tkl.tkl_init(tkl)
# cleanup
del tkl # must be instead of `tkl = None`, otherwise the variable would be still persist
sys.path.pop()
tkl_import_module(SOURCE_DIR, 'testlib.py')
print(globals().keys())
testlib.base_test()
testlib.testlib_std1.std1_test()
testlib.testlib_std1.testlib_std2.std2_test()
#testlib.testlib.std3.std3_test() # does not reachable directly ...
getattr(globals()['testlib'], 'testlib.std3').std3_test() # ... but reachable through the `globals` + `getattr`
tkl_import_module(SOURCE_DIR, 'testlib.py', '.')
print(globals().keys())
base_test()
testlib_std1.std1_test()
testlib_std1.testlib_std2.std2_test()
#testlib.std3.std3_test() # does not reachable directly ...
globals()['testlib.std3'].std3_test() # ... but reachable through the `globals` + `getattr`
testlib.py :
# optional for 3.4.x and higher
#import os, inspect
#
#SOURCE_FILE = os.path.abspath(inspect.getsourcefile(lambda:0)).replace('\\','/')
#SOURCE_DIR = os.path.dirname(SOURCE_FILE)
print("1 testlib::SOURCE_FILE: ", SOURCE_FILE)
tkl_import_module(SOURCE_DIR + '/std1', 'testlib.std1.py', 'testlib_std1')
# SOURCE_DIR is restored here
print("2 testlib::SOURCE_FILE: ", SOURCE_FILE)
tkl_import_module(SOURCE_DIR + '/std3', 'testlib.std3.py')
print("3 testlib::SOURCE_FILE: ", SOURCE_FILE)
def base_test():
print('base_test')
testlib.std1.py :
# optional for 3.4.x and higher
#import os, inspect
#
#SOURCE_FILE = os.path.abspath(inspect.getsourcefile(lambda:0)).replace('\\','/')
#SOURCE_DIR = os.path.dirname(SOURCE_FILE)
print("testlib.std1::SOURCE_FILE: ", SOURCE_FILE)
tkl_import_module(SOURCE_DIR + '/../std2', 'testlib.std2.py', 'testlib_std2')
def std1_test():
print('std1_test')
testlib.std2.py :
# optional for 3.4.x and higher
#import os, inspect
#
#SOURCE_FILE = os.path.abspath(inspect.getsourcefile(lambda:0)).replace('\\','/')
#SOURCE_DIR = os.path.dirname(SOURCE_FILE)
print("testlib.std2::SOURCE_FILE: ", SOURCE_FILE)
def std2_test():
print('std2_test')
testlib.std3.py :
# optional for 3.4.x and higher
#import os, inspect
#
#SOURCE_FILE = os.path.abspath(inspect.getsourcefile(lambda:0)).replace('\\','/')
#SOURCE_DIR = os.path.dirname(SOURCE_FILE)
print("testlib.std3::SOURCE_FILE: ", SOURCE_FILE)
def std3_test():
print('std3_test')
Saída ( 3.7.4
):
test::SOURCE_FILE: <root>/test01/test.py
import : <root>/test01/testlib.py as testlib -> []
1 testlib::SOURCE_FILE: <root>/test01/testlib.py
import : <root>/test01/std1/testlib.std1.py as testlib_std1 -> ['testlib']
import : <root>/test01/std1/../std2/testlib.std2.py as testlib_std2 -> ['testlib', 'testlib_std1']
testlib.std2::SOURCE_FILE: <root>/test01/std1/../std2/testlib.std2.py
2 testlib::SOURCE_FILE: <root>/test01/testlib.py
import : <root>/test01/std3/testlib.std3.py as testlib.std3 -> ['testlib']
testlib.std3::SOURCE_FILE: <root>/test01/std3/testlib.std3.py
3 testlib::SOURCE_FILE: <root>/test01/testlib.py
dict_keys(['__name__', '__doc__', '__package__', '__loader__', '__spec__', '__annotations__', '__builtins__', '__file__', '__cached__', 'os', 'sys', 'inspect', 'copy', 'SOURCE_FILE', 'SOURCE_DIR', 'TackleGlobalImportModuleState', 'tkl_membercopy', 'tkl_merge_module', 'tkl_get_parent_imported_module_state', 'tkl_declare_global', 'tkl_import_module', 'TackleSourceModuleState', 'tkl_source_module', 'TackleLocalImportModuleState', 'testlib'])
base_test
std1_test
std2_test
std3_test
import : <root>/test01/testlib.py as . -> []
1 testlib::SOURCE_FILE: <root>/test01/testlib.py
import : <root>/test01/std1/testlib.std1.py as testlib_std1 -> ['testlib']
import : <root>/test01/std1/../std2/testlib.std2.py as testlib_std2 -> ['testlib', 'testlib_std1']
testlib.std2::SOURCE_FILE: <root>/test01/std1/../std2/testlib.std2.py
2 testlib::SOURCE_FILE: <root>/test01/testlib.py
import : <root>/test01/std3/testlib.std3.py as testlib.std3 -> ['testlib']
testlib.std3::SOURCE_FILE: <root>/test01/std3/testlib.std3.py
3 testlib::SOURCE_FILE: <root>/test01/testlib.py
dict_keys(['__name__', '__doc__', '__package__', '__loader__', '__spec__', '__annotations__', '__builtins__', '__file__', '__cached__', 'os', 'sys', 'inspect', 'copy', 'SOURCE_FILE', 'SOURCE_DIR', 'TackleGlobalImportModuleState', 'tkl_membercopy', 'tkl_merge_module', 'tkl_get_parent_imported_module_state', 'tkl_declare_global', 'tkl_import_module', 'TackleSourceModuleState', 'tkl_source_module', 'TackleLocalImportModuleState', 'testlib', 'testlib_std1', 'testlib.std3', 'base_test'])
base_test
std1_test
std2_test
std3_test
Testado em Python 3.7.4
, 3.2.5
,2.7.16
Prós :
testlib.std.py
como testlib
, testlib.blabla.py
como testlib_blabla
e assim por diante).sys.path
armazenamento de caminho de pesquisa que nunca.SOURCE_FILE
e SOURCE_DIR
entre chamadas para tkl_import_module
.3.4.x
e superior] Pode misturar os namespaces do módulo em tkl_import_module
chamadas aninhadas (ex: named->local->named
ou local->named->local
assim por diante).3.4.x
and later] Pode exportar automaticamente variáveis / funções / classes globais de onde está declarada para todos os módulos filhos importados por meio da tkl_import_module
(por meio da tkl_declare_global
função).Contras :
3.3.x
and lower] Exigir declarar tkl_import_module
em todos os módulos que chama tkl_import_module
(duplicação de código)Atualização 1,2 ( 3.4.x
somente para versões superiores):
No Python 3.4 e superior, você pode ignorar o requisito de declarar tkl_import_module
em cada módulo, declarando tkl_import_module
em um módulo de nível superior, e a função se injetaria em todos os módulos filhos em uma única chamada (é um tipo de importação de auto-implantação).
Atualização 3 :
Adicionada função tkl_source_module
como analógica ao bash source
com suporte à execução de proteção na importação (implementada através da mesclagem de módulos em vez de importação).
Atualização 4 :
Função adicionada tkl_declare_global
para exportar automaticamente uma variável global do módulo para todos os módulos filhos em que uma variável global do módulo não está visível porque não faz parte de um módulo filho.
Atualização 5 :
Todas as funções foram transferidas para a biblioteca tacklelib, veja o link acima.
Há um pacote dedicado a isso especificamente:
from thesmuggler import smuggle
# À la `import weapons`
weapons = smuggle('weapons.py')
# À la `from contraband import drugs, alcohol`
drugs, alcohol = smuggle('drugs', 'alcohol', source='contraband.py')
# À la `from contraband import drugs as dope, alcohol as booze`
dope, booze = smuggle('drugs', 'alcohol', source='contraband.py')
Ele foi testado em versões do Python (Jython e PyPy também), mas pode ser um exagero, dependendo do tamanho do seu projeto.
Adicionando isso à lista de respostas, pois não consegui encontrar nada que funcionasse. Isso permitirá a importação de módulos python compilados (pyd) no 3.4:
import sys
import importlib.machinery
def load_module(name, filename):
# If the Loader finds the module name in this list it will use
# module_name.__file__ instead so we need to delete it here
if name in sys.modules:
del sys.modules[name]
loader = importlib.machinery.ExtensionFileLoader(name, filename)
module = loader.load_module()
locals()[name] = module
globals()[name] = module
load_module('something', r'C:\Path\To\something.pyd')
something.do_something()
maneira bem simples: suponha que você queira importar o arquivo com o caminho relativo ../../MyLibs/pyfunc.py
libPath = '../../MyLibs'
import sys
if not libPath in sys.path: sys.path.append(libPath)
import pyfunc as pf
Mas se você conseguir sem um guarda, poderá finalmente ter um caminho muito longo
Uma solução simples usando em importlib
vez do imp
pacote (testado para Python 2.7, embora deva funcionar também para Python 3):
import importlib
dirname, basename = os.path.split(pyfilepath) # pyfilepath: '/my/path/mymodule.py'
sys.path.append(dirname) # only directories should be added to PYTHONPATH
module_name = os.path.splitext(basename)[0] # '/my/path/mymodule.py' --> 'mymodule'
module = importlib.import_module(module_name) # name space of defined module (otherwise we would literally look for "module_name")
Agora você pode usar diretamente o espaço para nome do módulo importado, assim:
a = module.myvar
b = module.myfunc(a)
A vantagem desta solução é que nem precisamos saber o nome real do módulo que gostaríamos de importar , para usá-lo em nosso código. Isso é útil, por exemplo, caso o caminho do módulo seja um argumento configurável.
sys.path
, que não se encaixa em todos os casos de uso.
sys.path.pop()
Esta resposta é um complemento à resposta de Sebastian Rittau, que responde ao comentário: "mas e se você não tiver o nome do módulo?" Essa é uma maneira rápida e suja de obter o nome provável do módulo python com um nome de arquivo - ele sobe na árvore até encontrar um diretório sem um __init__.py
arquivo e depois o transforma novamente em um nome de arquivo. Para o Python 3.4+ (usa pathlib), o que faz sentido, já que as pessoas do Py2 podem usar "imp" ou outras maneiras de fazer importações relativas:
import pathlib
def likely_python_module(filename):
'''
Given a filename or Path, return the "likely" python module name. That is, iterate
the parent directories until it doesn't contain an __init__.py file.
:rtype: str
'''
p = pathlib.Path(filename).resolve()
paths = []
if p.name != '__init__.py':
paths.append(p.stem)
while True:
p = p.parent
if not p:
break
if not p.is_dir():
break
inits = [f for f in p.iterdir() if f.name == '__init__.py']
if not inits:
break
paths.append(p.stem)
return '.'.join(reversed(paths))
Certamente, existem possibilidades de aprimoramento, e os __init__.py
arquivos opcionais podem exigir outras alterações, mas se você tiver, __init__.py
em geral, isso funciona.
A melhor maneira, eu acho, é da documentação oficial ( 29.1. Imp - Acesse as informações internas de importação ):
import imp
import sys
def __import__(name, globals=None, locals=None, fromlist=None):
# Fast path: see if the module has already been imported.
try:
return sys.modules[name]
except KeyError:
pass
# If any of the following calls raises an exception,
# there's a problem we can't handle -- let the caller handle it.
fp, pathname, description = imp.find_module(name)
try:
return imp.load_module(name, fp, pathname, description)
finally:
# Since we may exit via an exception, close fp explicitly.
if fp:
fp.close()