Como importar um módulo com a localização completa?

Como posso carregar um módulo Python dado o seu caminho completo? Note que o arquivo pode estar em qualquer lugar do sistema de arquivos, pois é uma opção de configuração.

Author: ferkulat, 2008-09-16

24 answers

Para o Python 3. 5 + usar:

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 o Python 3.3 e 3.4 usar:

from importlib.machinery import SourceFileLoader

foo = SourceFileLoader("module.name", "/path/to/file.py").load_module()
foo.MyClass()

(embora isto tenha sido depreciado no Python 3.4.)

Python 2 Usar:

import imp

foo = imp.load_source('module.name', '/path/to/file.py')
foo.MyClass()

Existem funções de conveniência equivalentes para ficheiros Python compilados e DLLs.

Ver também. http://bugs.python.org/issue21436.

 926
Author: Sebastian Rittau, 2015-12-07 14:31:23

A vantagem de adicionar um caminho ao sys.o caminho (sobre usar o 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
 324
Author: Daryl Spitzer, 2008-09-24 19:36:16

Você também pode fazer algo parecido com isto e adicionar a pasta em que o ficheiro de configuração está sentado na localização de carga em Python, e depois fazer uma importação normal, assumindo que você sabe o nome do ficheiro com antecedência, neste caso "configuração".

Confuso, mas funciona.
configfile = '~/config.py'

import os
import sys

sys.path.append(os.path.dirname(os.path.expanduser(configfile)))

import config
 19
Author: ctcherry, 2014-01-17 22:38:07

Pode usar o

load_source(module_name, path_to_file) 

Método de módulo imp .

 16
Author: zuber, 2014-11-11 07:07:34

Parece que você não quer especificamente importar o arquivo de configuração (que tem um monte de efeitos colaterais e complicações adicionais envolvidos), você apenas deseja executá-lo, e ser capaz de acessar o espaço de nomes 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 em Python 2.7 e Python 3. 2+

 14
Author: ncoghlan, 2016-05-20 06:52:17
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')
 10
Author: Chris Calloway, 2008-09-16 01:43:04
Queres dizer carregar ou importar? Podes manipular o sistema.lista de localização indique a localização do seu módulo, importando depois o seu módulo. Por exemplo, dado um módulo em:
/foo/bar.py

Podias fazer:

import sys
sys.path[0:0] = '/foo' # puts the /foo directory at the start of your path
import bar
 9
Author: Wheat, 2010-07-09 05:30:00

Acho que podes usar imp.find_module() e imp.load_module() para carregar o módulo especificado. Você terá que dividir o nome do módulo do caminho, ou seja, se você quisesse carregar /home/mypath/mymodule.py você teria que fazer:

imp.find_module('mymodule', '/home/mypath/')

...mas isso deve fazer o trabalho.

 8
Author: Matt, 2015-01-02 11:08:38

Aqui está algum código que funciona em todas as versões Python, de 2.7-3.5 e provavelmente até mesmo outros.

config_file = "/tmp/config.py"
with open(config_file) as f:
    code = compile(f.read(), config_file, 'exec')
    exec(code, globals(), locals())
Testei-o. Pode ser feio, mas até agora é o único que funciona em todas as versões.
 7
Author: sorin, 2016-06-03 10:04:52
(Para Python > 3.4 eu acho), que lhe permitirá carregar um arquivo com qualquer extensão como um módulo usando spec_from_loader Em 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 a maquinaria não vai tentar descobrir o tipo de ficheiro a partir da extensão. Isso significa que você pode carregar algo como um .txt ficheiro usando este método, mas não o pôde fazer com {[[2]} sem especificar o carregador porque .txt não está em importlib.machinery.SOURCE_SUFFIXES.

 6
Author: Mad Physicist, 2018-09-19 18:13:16

Se o seu módulo de Topo não for um ficheiro, mas for empacotado como uma pasta com __ _ init__.py, então a solução Aceita quase funciona, mas não completamente. No Python 3.5+ é necessário o seguinte código (note a linha adicionada que começa com ' sys.módulos'):

MODULE_PATH = "/path/to/your/module/__init__.py"
MODULE_NAME = "mymodule"
spec = importlib.util.spec_from_file_location("mymodule", MODULE_PATH)
module = importlib.util.module_from_spec(spec)
sys.modules[spec.name] = module 
spec.loader.exec_module(module)

Sem esta linha, quando o exec_ Module é executado, ele tenta ligar as importações relativas no seu nível superior __init__.py para o nome do módulo de topo -- neste caso "mymodule". Mas o "mymodule" ainda não está carregado, por isso vais ter o erro. "SystemError: o módulo-mãe 'mymodule' não foi carregado, não é possível efectuar a importação relativa". Tens de ligar o nome antes de carregá-lo. The reason for this is the fundamental invariant of the relative import system: "The invariant holding is that if you have sys.módulos ['spam'] e sys.módulos ['spam.foo'] (como você faria após a importação acima), este último deve aparecer como o atributo foo do primeiro " Como discutido aqui .

 5
Author: Sam Grondahl, 2018-05-17 15:23:41

Isto 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)
 3
Author: Hengjie, 2012-01-04 04:28:50
Esta área do Python 3.4 parece ser extremamente tortuosa para entender! No entanto, com um pouco de hacking usando o código de Chris Calloway como um começo eu 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

Isto parece usar módulos não obsoletos do Python 3.4. Não pretendo entender porquê, mas parece funcionar dentro de um programa. Achei que a solução do Chris funcionava na linha de comando, mas não dentro de um programa.

 3
Author: Redlegjed, 2015-04-12 12:22:56
Não estou a dizer que seja melhor, mas por uma questão de exaustividade, queria sugerir que ... exec Função, Disponível em ambos python 2 e 3. exec permite-lhe executar um código arbitrário, quer no âmbito global, quer num âmbito interno, fornecido como um dicionário.

Por exemplo, se tiver um módulo armazenado em "/path/to/module " com a função foo(), pode executá-lo fazendo o seguinte:

module = dict()
with open("/path/to/module") as f:
    exec(f.read(), module)
module['foo']()
Isto torna um pouco mais explícito que estás a carregar código. dynamically, and grants you some additional power, such as the ability to provide custom builtins.

E se ter acesso através de atributos, em vez de chaves, é importante para ti, podes desenhar uma classe dict personalizada para os globais, que fornece esse acesso, por exemplo:

class MyModuleClass(dict):
    def __getattr__(self, name):
        return self.__getitem__(name)
 3
Author: yoniLavi, 2015-06-02 19:57:46

Para importar um módulo de um dado nome de ficheiro, poderá Extender temporariamente a localização e repor a localização do sistema na referência do 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
 3
Author: Peter Zhu, 2015-10-02 11:14:13

Importar módulos de pacotes à hora de execução (receita em 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)
 2
Author: user10370, 2013-12-22 02:17:57

Pode usar o módulo pkgutil (especificamente o walk_packages método) para obter uma lista dos pacotes no diretório atual. A partir daí é trivial usar a maquinaria importlib para importar os módulos que você quer:

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!
 2
Author: bob_twinkles, 2015-01-02 11:04:17

No Linux, a adição de uma ligação simbólica na pasta onde o seu programa em python está localizado funciona.

Ie:

ln -s /absolute/path/to/module/module.py /absolute/path/to/script/module.py

O Python irá criar /absolute/path/to/script/module.pyc e actualizá-lo-á se alterar o conteúdo do /absolute/path/to/module/module.py

Depois incluir o seguinte em mypythonscript.py

from module import *
 2
Author: user2760152, 2018-04-11 17:21:07
Fiz um pacote que usa imppara ti. Eu chamo-lhe 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')

Podes obtê-lo em:

Http://pypi.python.org/pypi/import_file

Ou em

Http://code.google.com/p/import-file/

 1
Author: ubershmekel, 2011-06-08 19:41:29

Uma forma bastante simples: suponha que deseja importar o ficheiro com a localização relativa .. / ../MyLibs/pyfunc.py


libPath = '../../MyLibs'
import sys
if not libPath in sys.path: sys.path.append(libPath)
import pyfunc as pf
Mas se conseguires sem um guarda, podes finalmente ter um caminho muito longo.
 1
Author: Andrei Keino, 2018-01-26 04:52:15

Uma solução simples usando importlib em vez do pacote imp (testado para o Python 2.7, embora também deva funcionar para o 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 pode usar directamente o espaço de nomes do módulo importado, do seguinte modo:

a = module.myvar
b = module.myfunc(a)

A vantagem desta solução é que nós nem precisamos saber o nome real do módulo que gostaríamos de importar {[[11]}, a fim de usá-lo em nosso código. Isto é útil, por exemplo, no caso de o caminho do Módulo ser um argumento configurável.

 1
Author: Ataxias, 2018-07-28 02:24:45
Adicionando isto à lista de respostas, não encontrei nada que funcionasse. Isto permitirá a importação de Módulos python compilados (pyd) em 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()
 0
Author: David, 2018-01-10 15:58:46

Esta resposta é um suplemento da resposta de Sebastian Rittau respondendo ao comentário: "mas e se você não tem o nome do módulo?"Esta é uma maneira rápida e suja de obter o nome provável do módulo python com um nome de arquivo -- ele apenas sobe a árvore até encontrar um diretório sem um arquivo __init__.py e então transforma-o de volta em um nome de arquivo. Para o Python 3.4+ (usa pathlib), o que faz sentido uma vez que o Py2 as pessoas podem usar o "imp"ou outras formas 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))
Existem certamente possibilidades de melhoria, e os arquivos opcionais __init__.py podem necessitar de outras alterações, mas se você tem __init__.py em geral, isso faz o truque.
 0
Author: Michael Scott Cuthbert, 2018-09-08 15:29:30
A melhor maneira, penso eu, é através da documentação oficial ([[3]}29.1. imp-aceder aos internos 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()
 -1
Author: Zompa, 2014-11-25 12:58:47