¿Cómo importar un módulo dado el camino completo?

¿Cómo puedo cargar un módulo Python dada su ruta completa? Tenga en cuenta que el archivo puede estar en cualquier parte del sistema de archivos, ya que es una opción de configuración.

Para uso de Python 3.5+:

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 el uso de Python 3.3 y 3.4:

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

(Aunque esto ha quedado en desuso en Python 3.4.)

Uso de Python 2:

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

Hay funciones de conveniencia equivalentes para los archivos comstackdos de Python y las DLL.

Ver también. http://bugs.python.org/issue21436 .

La ventaja de agregar una ruta a sys.path (sobre el uso de imp) es que simplifica las cosas al importar más de un módulo desde un solo paquete. Por ejemplo:

 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 

También puede hacer algo como esto y agregar el directorio donde se encuentra el archivo de configuración en la ruta de carga de Python, y luego hacer una importación normal, asumiendo que conoce el nombre del archivo de antemano, en este caso “config”.

Desordenado, pero funciona.

 configfile = '~/config.py' import os import sys sys.path.append(os.path.dirname(os.path.expanduser(configfile))) import config 

Parece que no desea importar específicamente el archivo de configuración (que tiene una gran cantidad de efectos secundarios y complicaciones adicionales involucradas), simplemente desea ejecutarlo y poder acceder al espacio de nombres resultante. La biblioteca estándar proporciona una API específica para eso en forma de runpy.run_path :

 from runpy import run_path settings = run_path("/path/to/file.py") 

Esa interfaz está disponible en Python 2.7 y Python 3.2+

Puedes usar el

 load_source(module_name, path_to_file) 

Método del módulo imp .

He encontrado una versión ligeramente modificada de la maravillosa respuesta de @ SebastianRittau (para Python> 3.4, creo), que te permitirá cargar un archivo con cualquier extensión como módulo usando spec_from_loader lugar 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) 

La ventaja de codificar la ruta en un SourceFileLoader explícito es que la maquinaria no intentará averiguar el tipo de archivo a partir de la extensión. Esto significa que puede cargar algo como un archivo .txt usando este método, pero no puede hacerlo con spec_from_file_location sin especificar el cargador porque .txt no está en importlib.machinery.SOURCE_SUFFIXES .

Aquí hay un código que funciona en todas las versiones de Python, desde 2.7-3.5 y probablemente hasta otras.

 config_file = "/tmp/config.py" with open(config_file) as f: code = compile(f.read(), config_file, 'exec') exec(code, globals(), locals()) 

Lo he probado. Puede ser feo, pero hasta ahora es el único que funciona en todas las versiones.

¿Te refieres a cargar o importar?

Puede manipular la lista sys.path para especificar la ruta a su módulo y luego importar su módulo. Por ejemplo, dado un módulo en:

 /foo/bar.py 

Podrías hacerlo:

 import sys sys.path[0:0] = ['/foo'] # puts the /foo directory at the start of your path import bar 
 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') 

Si su módulo de nivel superior no es un archivo, pero está empaquetado como un directorio con __init__.py, la solución aceptada casi funciona, pero no del todo. En Python 3.5+ se necesita el siguiente código (note la línea agregada que comienza con ‘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) 

Sin esta línea, cuando se ejecuta exec_module, intenta vincular las importaciones relativas en su nivel superior __init__.py al nombre del módulo de nivel superior, en este caso “mymodule”. Pero “mymodule” aún no está cargado, por lo que aparecerá el error “SystemError: el módulo principal ‘mymodule’ no está cargado, no se puede realizar una importación relativa”. Así que necesitas unir el nombre antes de cargarlo. La razón de esto es la invariante fundamental del sistema de importación relativo: “La invariable es que si tiene sys.modules [‘spam’] y sys.modules [‘spam.foo’] (como lo haría después de la importación anterior ), el último debe aparecer como el atributo foo del primero ” como se explica aquí .

Para importar su módulo, necesita agregar su directorio a la variable de entorno, ya sea temporal o permanentemente.

Temporalmente

 import sys sys.path.append("/path/to/my/modules/") import my_module 

Permanentemente

Agregando la siguiente línea a su archivo .bashrc (en linux) y ejecute la source ~/.bashrc en el terminal:

 export PYTHONPATH="${PYTHONPATH}:/path/to/my/modules/" 

Crédito / Fuente: saarrrr , otra pregunta de intercambio de stack

Creo que puedes usar imp.find_module() y imp.load_module() para cargar el módulo especificado. Deberá separar el nombre del módulo de la ruta, es decir, si desea cargar /home/mypath/mymodule.py , deberá hacer:

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

… pero eso debería hacer el trabajo

Esto debería 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) 

Puede usar el módulo pkgutil (específicamente el método walk_packages ) para obtener una lista de los paquetes en el directorio actual. Desde allí es trivial utilizar la maquinaria importlib para importar los módulos que desee:

 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! 

¡Esta área de Python 3.4 parece ser extremadamente tortuosa de entender! Sin embargo, con un poco de pirateo usando el código de Chris Calloway como comienzo, logré que algo funcionara. Aquí está la función 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 

Esto parece utilizar módulos no desaprobados de Python 3.4. No pretendo entender por qué, pero parece funcionar desde dentro de un progtwig. Encontré que la solución de Chris funcionaba en la línea de comandos pero no desde dentro de un progtwig.

No estoy diciendo que sea mejor, pero en aras de la exhaustividad, quería sugerir la función exec , disponible tanto en python 2 como en 3. exec permite ejecutar código arbitrario en el ámbito global o de forma interna. scope, proporcionado como un diccionario.

Por ejemplo, si tiene un módulo almacenado en "/path/to/module ” con la función foo() , puede ejecutarlo haciendo lo siguiente:

 module = dict() with open("/path/to/module") as f: exec(f.read(), module) module['foo']() 

Esto hace que sea un poco más explícito que está cargando el código dinámicamente y le otorga un poco de poder adicional, como la capacidad de proporcionar elementos personalizados.

Y si tener acceso a través de atributos, en lugar de claves es importante para usted, puede diseñar una clase de dictados personalizados para los globales, que proporcione dicho acceso, por ejemplo:

 class MyModuleClass(dict): def __getattr__(self, name): return self.__getitem__(name) 

Para importar un módulo desde un nombre de archivo dado, puede extender temporalmente la ruta y restaurar la ruta del sistema en la referencia del bloque final:

 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 # restre 

Crear el módulo de python test.py

 import sys sys.path.append("/lib/") from tes1 import Client1 from tes2 import Client2 import tes3 

Crear el módulo python test_check.py

 from test import Client1 from test import Client2 from test import test3 

Podemos importar el módulo importado desde el módulo.

Hice un paquete que utiliza imp para usted. Lo llamo import_file y así es como se usa:

 >>>from import_file import import_file >>>mylib = import_file('c:\\mylib.py') >>>another = import_file('relative_subdir/another.py') 

Puedes conseguirlo en:

http://pypi.python.org/pypi/import_file

o en

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

Importar módulos de paquetes en tiempo de ejecución (receta de 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) 

En Linux, agregar un enlace simbólico en el directorio donde se encuentra su script de Python funciona.

es decir:

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

python creará /absolute/path/to/script/module.pyc y lo actualizará si cambias el contenido de /absolute/path/to/module/module.py

Luego incluya lo siguiente en mypythonscript.py

 from module import * 

forma bastante simple: suponga que desea importar un archivo con una ruta relativa ../../MyLibs/pyfunc.py

 libPath = '../../MyLibs' import sys if not libPath in sys.path: sys.path.append(libPath) import pyfunc as pf 

Pero si lo haces sin guardia, finalmente puedes obtener un camino muy largo.

Una solución simple que utiliza importlib lugar del paquete imp (probado para Python 2.7, aunque también debería funcionar 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") 

Ahora puedes usar directamente el espacio de nombres del módulo importado, de esta manera:

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

La ventaja de esta solución es que ni siquiera necesitamos saber el nombre real del módulo que nos gustaría importar para usarlo en nuestro código. Esto es útil, por ejemplo, en caso de que la ruta del módulo sea un argumento configurable.

Agregando esto a la lista de respuestas ya que no pude encontrar nada que funcionara. Esto permitirá la importación de módulos de Python comstackdos (pyd) en 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() 

Esta respuesta es un suplemento a la respuesta de Sebastian Rittau que responde al comentario: “pero, ¿y si no tiene el nombre del módulo?” Esta es una forma rápida y sucia de obtener el nombre del módulo python que se le da a un nombre de archivo; simplemente sube el árbol hasta que encuentra un directorio sin un archivo __init__.py y luego lo convierte de nuevo en un nombre de archivo. Para Python 3.4+ (usa pathlib), lo cual tiene sentido ya que las personas de Py2 pueden usar “imp” u otras formas de hacer importaciones 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)) 

Ciertamente hay posibilidades de mejora, y los archivos opcionales __init__.py pueden requerir otros cambios, pero si tienes __init__.py en general, esto funciona.

Creo que la mejor manera es a partir de la documentación oficial ( 29.1. Imp – Acceda a los documentos internos de importación ):

 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()