HOWTO · Python

Importar un módulo desde una ruta de archivo completa en Python

Este artículo le muestra cómo importar un archivo Python desde una ruta.

En esta página

Importar un módulo desde una ruta de archivo específica resulta útil cuando un complemento, un archivo generado o un script independiente queda fuera de la estructura habitual de paquetes. Para importar un módulo una sola vez, importlib.util crea un objeto de módulo y su cargador ejecuta el archivo en el espacio de nombres de ese módulo. Registre el módulo en sys.modules antes de ejecutarlo para que el código que consulta el registro durante la inicialización pueda encontrar su propio módulo.

Importar un archivo Python por su ruta con importlib.util

Asigne al archivo un nombre de módulo válido en Python y especifique su ruta exacta. El nombre es un identificador del objeto de módulo; no tiene que coincidir con el nombre del archivo, pero conviene que sea lo bastante exclusivo para su aplicación. El ejemplo crea un archivo Python temporal para poder ejecutarse con independencia del directorio de trabajo actual.

Ejecute este ejemplo:

El código y las etiquetas o salidas visibles de esta sección se mantienen en inglés.

from pathlib import Path
import importlib.util
import sys
import tempfile

with tempfile.TemporaryDirectory() as directory:
    module_path = Path(directory) / "greeting.py"
    module_path.write_text("def message():\n    return 'loaded from path'\n", encoding="utf-8")
    module_name = "greeting_from_path"
    spec = importlib.util.spec_from_file_location(module_name, module_path)
    module = importlib.util.module_from_spec(spec)
    sys.modules[module_name] = module
    spec.loader.exec_module(module)
    print(module.message())

La última llamada imprime el valor que devuelve la función del archivo cargado. spec_from_file_location() crea una especificación de módulo que describe el nombre y la ubicación. module_from_spec() crea el módulo a partir de esa especificación, y exec_module() ejecuta su código fuente mediante el cargador. Si la ruta se proporciona dinámicamente, compruebe que la especificación y el cargador estén disponibles antes de usar este patrón: un archivo inexistente o un cargador no compatible impiden importarlo de este modo.

Añadir el directorio del archivo a sys.path

Si quiere importar módulos de un directorio mediante las importaciones habituales, añada a sys.path el directorio que contiene el archivo y luego impórtelo por su nombre de módulo. sys.path es la lista de ubicaciones en las que Python busca módulos. Este ejemplo autónomo crea un módulo en un directorio temporal, añade el directorio que lo contiene e importa el módulo por su nombre:

Ejecute este ejemplo:

El código y las etiquetas o salidas visibles de esta sección se mantienen en inglés.

from pathlib import Path
import importlib
import sys
import tempfile

with tempfile.TemporaryDirectory() as directory:
    module_name = f"greeting_{Path(directory).name}"
    module_path = Path(directory) / f"{module_name}.py"
    module_path.write_text("def message():\n    return 'loaded by name'\n", encoding="utf-8")
    sys.path.insert(0, directory)
    try:
        module = importlib.import_module(module_name)
        print(module.message())
    finally:
        sys.path.remove(directory)
        sys.modules.pop(module_name, None)

Añadir o insertar un directorio modifica las búsquedas durante el resto del proceso en ejecución. Por eso, limite el cambio de ruta al ámbito más reducido posible y evite añadir directorios que controlen usuarios no confiables. Después, el ejemplo elimina la entrada de la ruta y el módulo almacenado en caché para limitar sus efectos. Este método resulta práctico cuando quiere usar deliberadamente la sintaxis de importación habitual o necesita varios módulos del mismo directorio. Sigue aplicando las reglas normales de resolución de nombres y almacenamiento en caché: puede reutilizarse un módulo que ya esté en sys.modules, y un nombre en conflicto podría resolver a un archivo distinto del esperado.

Usar exec() solo para ejecutar texto de script confiable

exec() ejecuta código fuente de Python en un espacio de nombres proporcionado; no crea ni registra un objeto de módulo normal. Úselo solo si la tarea consiste en ejecutar el contenido de un script confiable, no como sustituto de la importación de un módulo. Ejecutar texto procedente de una carga, una solicitud u otra fuente no confiable puede ejecutar código Python arbitrario con los permisos del proceso. Un diccionario independiente puede almacenar los nombres que cree el script, pero no ofrece todo el comportamiento de importación ni la identidad de módulo de un módulo real.

Gestionar nombres de módulo, paquetes y errores de importación

Use un identificador válido como nombre de un módulo sencillo y elija un nombre único y estable si va a cargar varios archivos. Reutilizar el mismo nombre afecta a sys.modules: cargar otro archivo con ese nombre puede reemplazar la entrada del registro, mientras que una importación habitual posterior podría devolver un módulo que ya esté en la caché. Decida si las llamadas repetidas deben reutilizar un módulo o cargar uno nuevo deliberadamente.

Un archivo cargado directamente por su ruta no pasa a formar parte de su paquete automáticamente. El código que usa importaciones relativas, como from .helpers import value, depende del contexto del paquete, que una especificación para un solo archivo no recrea por sí sola. Para un paquete, es preferible importarlo mediante su nombre de paquete y tener su directorio padre disponible en sys.path. Si falla la carga, compruebe que la ruta apunte a un archivo Python legible, que se haya creado la especificación y que el cargador esté disponible; después, consulte el traceback de la ejecución del módulo para averiguar la causa. El propio código de inicialización puede fallar, así que una ruta válida no garantiza por sí sola una inicialización correcta.

Elegir el método adecuado

Elija importlib.util para importar una sola vez desde una ruta de archivo específica cuando necesite un objeto de módulo. Añada un directorio a sys.path cuando quiera que participe en las búsquedas de importación habituales, sobre todo si va a usar varios módulos relacionados. Elija exec() solo si quiere ejecutar código fuente confiable como script y no necesita la semántica de un módulo. Para el código reutilizable de un proyecto, normalmente resulta más sencillo gestionar dependencias, nombres y caché con un paquete convencional y las importaciones habituales.