modulefinder en Python: descubre imports

Publicado el: 27/08/2026
Tempo de leitura: 7 minutos
Colorful stacked shipping containers at Hamburg port, showcasing global trade and logistics.

El módulo modulefinder analiza un script Python e intenta descubrir los módulos importados directa y transitivamente. Inspecciona code objects, sigue instrucciones de importación, consulta paths configurados y construye un inventario útil para packagers, auditorías, herramientas de build, informes de dependencias y diagnóstico de imports ausentes.

El análisis no es completo. Python permite imports dinámicos, plugins, ejecución condicional, cambios de sys.path y nombres construidos en runtime. Trata el resultado como una aproximación estática basada en el código disponible, no como prueba de todo lo que la aplicación cargará.

Crea un ModuleFinder

La clase principal es modulefinder.ModuleFinder.

from modulefinder import ModuleFinder

finder = ModuleFinder()
finder.run_script("app.py")

Después del análisis, el objeto contiene módulos encontrados, referencias ausentes y datos para informes.

Lista los módulos encontrados

El atributo modules mapea nombres a objetos analizados.

for nombre in sorted(finder.modules):
    modulo = finder.modules[nombre]
    print(nombre, modulo.__file__)

No todos poseen archivo normal. Builtins, extensiones, namespaces y loaders especiales pueden usar representaciones diferentes.

Usa report

report() imprime un resumen legible.

finder.report()

Es cómodo para investigación manual. En automatización, recorre atributos y genera JSON u otro formato estructurado.

Imports directos y transitivos

Al analizar un script, modulefinder sigue imports de los módulos descubiertos. El inventario incluye dependencias transitivas, no solo líneas del entry point.

Un import aparentemente pequeño puede traer un árbol grande.

Configura el path

El constructor acepta un path con directorios de búsqueda.

import sys
from modulefinder import ModuleFinder

finder = ModuleFinder(path=["src", *sys.path])
finder.run_script("src/app.py")

Usa el mismo entorno y layout de runtime. Un path distinto puede elegir otro paquete con el mismo nombre.

Entornos virtuales

Ejecuta dentro del venv con las dependencias reales. Mezclar paths globales y del proyecto produce resultados engañosos.

Registra sys.executable, versión y paths utilizados.

Layout src

Los proyectos con paquetes bajo src/ necesitan incluir esa raíz o instalar el paquete.

Analizar la distribución instalada reproduce mejor namespaces, metadatos y comportamiento de importación.

Imports relativos

Los imports relativos dependen del contexto del paquete. Ejecutar un módulo interno como script puede cambiar el significado o fallar.

Analiza el entry point real y la estructura correcta.

Imports condicionales

Un import dentro de un if puede detectarse aunque la condición no sea verdadera en la plataforma actual.

if sys.platform == "win32":
    import winreg

El informe puede incluir dependencias opcionales de otros sistemas. Clasifícalas en lugar de eliminarlas ciegamente.

Imports opcionales con try/except

Las bibliotecas suelen intentar un acelerador y usar fallback.

try:
    import acelerador
except ImportError:
    import implementacion_python

El análisis puede listar ambos o marcar uno ausente. No significa automáticamente que la aplicación esté rota.

Imports dinámicos

importlib.import_module(nombre) puede recibir un valor conocido solo en runtime.

backend = importlib.import_module(config["backend"])

Las herramientas estáticas quizá no determinen el nombre. Los packagers suelen requerir hidden imports explícitos.

El builtin __import__

__import__() también puede cargar nombres calculados.

Revisa configuración, registries y convenciones de plugins además del informe.

Sistemas de plugins

Los plugins pueden descubrirse mediante entry points, directorios, bases o configuración, sin import directo.

Combina modulefinder con importlib.metadata.entry_points(), tema posterior de este lote.

Namespace packages

Un namespace package puede abarcar varios directorios y distribuciones. Ejecuta la herramienta en el entorno instalado completo.

No supongas que un único __file__ representa todo el namespace.

Extensiones nativas

Los módulos compilados pueden aparecer como .so, .pyd o equivalentes.

Modulefinder identifica el módulo, pero no enumera automáticamente bibliotecas nativas cargadas por él.

Módulos built-in

Los módulos integrados en el intérprete no tienen archivo Python común.

Un packager debe clasificarlos como parte del runtime.

Módulos frozen

Los ejecutables congelados pueden incluir módulos internamente. La representación depende del runtime y packager.

Prueba el artefacto final porque el análisis de desarrollo puede diferir.

badmodules

El finder mantiene nombres que no pudieron localizarse en ciertos contextos.

Un informe útil muestra qué módulos intentaron cada import. Un nombre ausente puede ser opcional para un paquete y obligatorio para otro.

any_missing

Métodos de conveniencia devuelven nombres considerados ausentes.

faltantes = finder.any_missing()
print(faltantes)

Revisa cada nombre antes de fallar el build, especialmente imports opcionales y de plataforma.

Ausentes posibles y definidos

Versiones compatibles pueden separar faltantes definitivos y posibles.

La clasificación ayuda a priorizar, pero sigue siendo heurística.

Excludes

El constructor acepta una lista de exclusión.

finder = ModuleFinder(
    excludes=["tkinter", "tests"],
)

Excluir indica que el análisis debe ignorar el módulo; no prueba que la aplicación nunca lo solicite.

Documenta exclusiones

Explica si cada módulo pertenece a otra plataforma, feature desactivada, herramienta de desarrollo o implementación alternativa.

Añade un test que confirme que el camino excluido no se alcanza.

replace_paths

replace_paths reemplaza prefijos en filenames registrados.

Esto hace informes reproducibles y evita paths temporales de CI.

Privacidad de paths

Los inventarios pueden revelar usernames, home directories y estructura interna.

Normaliza paths antes de compartir y restringe acceso.

Debug

El argumento debug aumenta logging interno.

finder = ModuleFinder(debug=2)

Úsalo localmente. Logs verbosos de CI pueden exponer paths y dificultar búsquedas.

run_script y load_file

run_script() analiza un script ejecutable; APIs relacionadas pueden cargar archivos en otros contextos.

Elige la operación que represente si el target es entry point o módulo de paquete.

Análisis basado en bytecode

Modulefinder examina code objects e instrucciones de importación, por lo que depende de detalles del compilador.

Ejecuta con la misma versión de Python del runtime objetivo.

Inspecciona con dis

Si un import se clasifica de forma inesperada, dis muestra las instrucciones generadas.

Consulta dis en Python.

Código no alcanzable

El análisis puede encontrar imports en funciones nunca llamadas, branches muertos y compatibilidad opcional.

Describe dependencias sintácticas posibles, no frecuencia ni reachability.

Combina análisis estático y dinámico

Registra módulos cargados durante tests representativos y compáralos con el inventario.

Los tests dinámicos omiten features no ejecutadas; el análisis estático omite nombres calculados. Juntos reducen huecos.

Auditoría de dependencias

El inventario revela módulos transitivos, pero no ofrece automáticamente distribución, versión, licencia o vulnerabilidad.

Mapea módulos a distribuciones con importlib.metadata.packages_distributions().

Standard library y terceros

Clasifica por origen: builtin, biblioteca estándar, proyecto y site-packages.

Usa sysconfig para ubicar la standard library. Consulta sysconfig en Python.

Shadowing

Varios directorios pueden proporcionar el mismo nombre. El orden define cuál se selecciona.

Registra el archivo elegido. Un json.py local puede ocultar la biblioteca estándar.

Imports desde ZIP

Las dependencias pueden venir de ZIP en sys.path. Confirma soporte del loader.

No supongas que cada módulo corresponde a un path normal.

Varios entry points

Un proyecto puede tener CLI, servidor web, worker y tareas con árboles diferentes.

Analiza cada entry point y une resultados conservando qué target requiere cada módulo.

Perfiles opcionales

Crea perfiles mínimo, GUI, cloud, base específica o datos.

Una lista global puede añadir dependencias grandes a artefactos que no las usan.

Salida estructurada

Convierte el resultado en una representación estable.

resultado = {
    nombre: {"archivo": modulo.__file__}
    for nombre, modulo in finder.modules.items()
}

Ordena claves para diffs reproducibles.

Grafos de dependencias

El mapping no siempre expone todas las aristas listo para visualizar.

Instrumenta la herramienta o combina AST. Usa graphlib en Python para orden topológico cuando corresponda.

Ciclos de import

Python permite algunos ciclos, pero el orden puede exponer módulos parcialmente inicializados.

Usa el inventario como señal y prueba imports en un proceso limpio.

Import hooks personalizados

Loaders e hooks pueden tener comportamiento especial.

Ejecuta el análisis en entorno aislado para proyectos que no controlas.

Límites de recursos

Árboles grandes consumen tiempo y memoria. Limita archivos, tamaño y duración.

Cachea por hash del entorno y entry point cuando el análisis se repite.

Proyectos subidos

Un servicio debería usar worker separado, filesystem temporal y permisos reducidos.

Valida archives antes de extraer e impide paths que escapen de la raíz.

Comparaciones en CI

Una pipeline puede comparar el inventario con una baseline revisada.

finder = ModuleFinder(path=paths)
finder.run_script(entrypoint)
nombres = sorted(finder.modules)

Solicita revisión para cambios significativos, no por cada diferencia de plataforma.

Pruebas

Cubre imports absolutos, relativos, condicionales, opcionales, dinámicos, namespace packages, extensiones, ZIP, faltantes, shadowing y varios entry points.

Ejecuta en todos los sistemas soportados.

Errores comunes

Los fallos frecuentes son tratar el resultado como completo, ignorar plugins dinámicos, usar el venv equivocado, analizar un módulo interno como script, fallar por opcionales, excluir sin tests, confundir módulo con distribución y no probar el artefacto.

Conclusión

modulefinder construye un inventario útil de imports directos y transitivos. Configura el path correcto, analiza cada entry point, revisa faltantes y añade información de plugins y runtime.

Trata la salida como aproximación y prueba la aplicación empaquetada. Consulta la documentación oficial de modulefinder y symtable en Python para análisis estático de nombres.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Contenido del artículo

    Artículos relacionados

    Person sorting documents in folders outdoors, hands visible, neutral tone.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    py_compile en Python: compila un archivo

    Aprende py_compile en Python para compilar un archivo, controlar .pyc, filenames lógicos, optimización, invalidación por hash y errores.

    Ler mais

    Tempo de leitura: 6 minutos
    27/08/2026
    A developer typing code on a laptop with a Python book beside in an office.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    compileall en Python: genera bytecode .pyc

    Aprende compileall en Python para generar .pyc, validar sintaxis, compilar en paralelo y controlar optimización, paths y builds reproducibles.

    Ler mais

    Tempo de leitura: 7 minutos
    27/08/2026
    Vivid close-up of code on a computer screen showcasing programming details.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    codeop en Python: compila entrada interactiva

    Aprende codeop en Python para detectar comandos completos, incompletos o inválidos, crear REPLs y conservar flags de __future__ de forma

    Ler mais

    Tempo de leitura: 7 minutos
    27/08/2026
    A close-up shot showcasing the intricate scales of a snake, highlighting texture and color.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    linecache en Python: lee líneas del código

    Aprende linecache en Python para recuperar líneas de código, actualizar cache, soportar tracebacks y loaders, conservar indentación y proteger rutas.

    Ler mais

    Tempo de leitura: 8 minutos
    27/08/2026
    Close-up view of a computer screen displaying code in a software development environment.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    faulthandler en Python: diagnostica fallos

    Aprende faulthandler en Python para diagnosticar crashes, deadlocks, señales fatales, timeouts y bloqueos con dumps de todas las threads.

    Ler mais

    Tempo de leitura: 9 minutos
    27/08/2026
    A detailed image of a reticulated python showcasing its patterned scales and intricate skin texture.
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    symtable en Python: analiza scopes

    Aprende symtable en Python para analizar scopes, locals, globals, parámetros, imports, nonlocals, closures y namespaces del compilador.

    Ler mais

    Tempo de leitura: 9 minutos
    27/08/2026