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.
1141
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:
Para Python 3.3 e 3.4, use:
(Embora isso tenha sido descontinuado no Python 3.4.)
Para Python 2, use:
Existem funções de conveniência equivalentes para arquivos e DLLs Python compilados.
Veja também http://bugs.python.org/issue21436 .
fonte
__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 nosys.modules
dicionário; portanto, o primeiro argumento realmente afeta o carregamento.imp
módulo está obsoleto desde a versão 3.4: Oimp
pacote está com obsoleta pendente em favor deimportlib
.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:
fonte
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 umsys.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'):
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 .
fonte
mymodule
?/path/to/your/module/
é realmente/path/to/your/PACKAGE/
? emymodule
você quer dizermyfile.py
?Para importar seu módulo, você precisa adicionar seu diretório à variável de ambiente, temporária ou permanentemente.
Temporariamente
Permanentemente
Adicionando a seguinte linha ao seu
.bashrc
arquivo (no linux) e executesource ~/.bashrc
no terminal:Crédito / Fonte: saarrrr , outra questão de stackexchange
fonte
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 :
Essa interface está disponível no Python 2.7 e Python 3.2 ou superior
fonte
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.
fonte
Você pode usar o
método do módulo imp .
fonte
imp.load_dynamic(module_name, path_to_file)
para DLLsfonte
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.
Eu testei. Pode ser feio, mas até agora é o único que funciona em todas as versões.
fonte
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 despec_from_file_location
: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 comspec_from_file_location
sem especificar o carregador, porque.txt
não está naimportlib.machinery.SOURCE_SUFFIXES
.fonte
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:Você poderia fazer:
fonte
sys.path[0:0] = ['/foo']
Explicit is better than implicit.
Então, por que não emsys.path.insert(0, ...)
vez desys.path[0:0]
?Eu acredito que você pode usar
imp.find_module()
eimp.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:... mas isso deve fazer o trabalho.
fonte
Você pode usar o
pkgutil
módulo (especificamente owalk_packages
método) para obter uma lista dos pacotes no diretório atual. A partir daí, é trivial usar oimportlib
maquinário para importar os módulos que você deseja:fonte
Criar módulo python test.py
Criar módulo python test_check.py
Podemos importar o módulo importado do módulo.
fonte
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.
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.
fonte
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., queexec
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çãofoo()
, poderá executá-lo da seguinte maneira: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:
fonte
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 :
fonte
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/
fonte
Isso deve funcionar
fonte
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 chamoimport_file
e é assim que é usado:Você pode obtê-lo em:
http://pypi.python.org/pypi/import_file
ou em
http://code.google.com/p/import-file/
fonte
Importar módulos de pacote em tempo de execução (receita Python)
http://code.activestate.com/recipes/223972/
fonte
No Linux, adicionar um link simbólico no diretório em que seu script python está localizado funciona.
ou seja:
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
fonte
git
e verificando o seugit 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:
Dependência e ordem de inclusão:
Implementação:
Armazenamento das últimas alterações: https://sourceforge.net/p/tacklelib/tacklelib/HEAD/tree/trunk/python/tacklelib/tacklelib.py
test.py :
testlib.py :
testlib.std1.py :
testlib.std2.py :
testlib.std3.py :
Saída (
3.7.4
):Testado em Python
3.7.4
,3.2.5
,2.7.16
Prós :
testlib.std.py
comotestlib
,testlib.blabla.py
comotestlib_blabla
e assim por diante).sys.path
armazenamento de caminho de pesquisa que nunca.SOURCE_FILE
eSOURCE_DIR
entre chamadas paratkl_import_module
.3.4.x
e superior] Pode misturar os namespaces do módulo emtkl_import_module
chamadas aninhadas (ex:named->local->named
oulocal->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 datkl_import_module
(por meio datkl_declare_global
função).Contras :
3.3.x
and lower] Exigir declarartkl_import_module
em todos os módulos que chamatkl_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, declarandotkl_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 bashsource
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.
fonte
Há um pacote dedicado a isso especificamente:
Ele foi testado em versões do Python (Jython e PyPy também), mas pode ser um exagero, dependendo do tamanho do seu projeto.
fonte
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:
fonte
maneira bem simples: suponha que você queira importar o arquivo com o caminho relativo ../../MyLibs/pyfunc.py
Mas se você conseguir sem um guarda, poderá finalmente ter um caminho muito longo
fonte
Uma solução simples usando em
importlib
vez doimp
pacote (testado para Python 2.7, embora deva funcionar também para Python 3):Agora você pode usar diretamente o espaço para nome do módulo importado, assim:
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.
fonte
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: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.fonte
A melhor maneira, eu acho, é da documentação oficial ( 29.1. Imp - Acesse as informações internas de importação ):
fonte