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

Publicado el: 27/08/2026
Tempo de leitura: 8 minutos
A close-up shot showcasing the intricate scales of a snake, highlighting texture and color.

El módulo linecache permite acceder eficientemente a líneas concretas de archivos de texto, con soporte especial para código fuente Python. Herramientas como traceback, debuggers, inspectores y analizadores lo utilizan para recuperar la línea asociada a un frame sin abrir y recorrer el archivo completo en cada consulta.

La API es pequeña, pero su comportamiento incluye un cache global del proceso, invalidación, reglas de encoding y soporte para módulos cargados mediante import hooks. Comprender estos detalles ayuda a construir diagnósticos, navegadores de código, editores y sistemas de informes más fiables.

Lee una línea

La función principal es linecache.getline(filename, lineno). La numeración comienza en 1.

import linecache

linea = linecache.getline("aplicacion.py", 12)
print(linea)

Un resultado correcto suele incluir la nueva línea final. Cuando el archivo o número no puede leerse, la función normalmente devuelve una string vacía en lugar de lanzar errores comunes de archivo.

La numeración comienza en uno

A diferencia de las listas Python, la primera línea es la línea 1. Esto coincide con tracebacks, editores, mensajes del compilador y posiciones de AST.

primera = linecache.getline("app.py", 1)

Valida números proporcionados por usuarios para evitar confusiones con cero, negativos o valores enormes.

Interpreta el resultado vacío

Una string vacía puede significar que el archivo no existe, la línea está fuera del rango, la lectura falló o el fuente no está disponible. La API está orientada a diagnósticos, donde no mostrar el fragmento es preferible a ocultar la excepción original.

Si necesitas distinguir causas, valida la ruta y lee el archivo directamente con manejo explícito de errores.

El cache global

Después de cargar un archivo, linecache mantiene información en un cache global del proceso. Las consultas posteriores evitan reabrir y recorrer el mismo archivo.

Esto resulta útil cuando un traceback necesita varias líneas. Las herramientas de larga duración deben considerar archivos desactualizados y memoria retenida.

Actualiza archivos modificados

checkcache() compara metadatos y elimina entradas aparentemente antiguas.

linecache.checkcache("aplicacion.py")
linea = linecache.getline("aplicacion.py", 12)

Sin filename, revisa las entradas apropiadas. Un editor o servidor de desarrollo puede ejecutarlo antes de mostrar fuente que quizá cambió.

Limpia el cache

clearcache() elimina todas las líneas almacenadas.

linecache.clearcache()

Es útil después de un análisis grande, al cambiar de workspace o cuando un proceso largo necesita liberar fuente.

No limpies en cada consulta

Limpiar constantemente elimina el beneficio de rendimiento. Invalida cuando exista un cambio conocido, al cerrar un proyecto o cuando las métricas muestren presión real de memoria.

Un file watcher puede llamar a checkcache() para paths modificados.

Usa module_globals cuando corresponda

getline() acepta un argumento opcional module_globals. Puede ayudar a encontrar fuente para módulos cuyo loader proporciona código sin archivo convencional.

linea = linecache.getline(
    filename,
    numero,
    module_globals=globals_modulo,
)

Esto importa para import hooks, módulos frozen, zip imports y loaders personalizados.

Loaders y get_source

Cuando existe un loader compatible, linecache puede pedir el código al sistema de importación, normalmente mediante get_source(). Por eso un traceback puede mostrar fuente aunque el filename no sea una ruta normal.

Los loaders personalizados deberían implementar correctamente los contratos para cooperar con debuggers y diagnósticos.

Fuente dentro de ZIP

Las aplicaciones distribuidas como ZIP o archivos .pyz pueden ejecutar módulos sin extraerlos. Un loader todavía puede exponer el fuente.

Consulta zipapp en Python para crear archivos ejecutables.

Código generado

El código compilado dinámicamente puede utilizar un filename simbólico en compile(). Si no existe archivo, cache o loader asociado, linecache no podrá recuperar la línea.

Los frameworks que generan código deberían conservar un mapeo controlado entre filenames simbólicos y fuente cuando el diagnóstico lo requiera.

Tracebacks

El módulo traceback usa linecache para mostrar la línea correspondiente a cada frame.

try:
    ejecutar()
except Exception:
    traceback.print_exc()

Si el archivo cambia después de cargar el código, la línea mostrada puede no coincidir con el bytecode en ejecución. Esto ocurre en deploys que sustituyen archivos sin reiniciar procesos.

Mantén código y fuente alineados

Evita modificar archivos usados por un proceso vivo. El runtime ejecuta code objects antiguos mientras el diagnóstico puede leer texto nuevo.

Deploys atómicos con directorios versionados y restart controlado conservan tracebacks correctos.

Encoding de fuente Python

Los archivos Python pueden declarar encoding. Linecache coopera con la maquinaria de lectura de fuente del intérprete.

Para leer un archivo completo explícitamente, usa tokenize.open(). Consulta tokenize en Python.

Nueva línea final

Las líneas devueltas normalmente incluyen \n. Elimina solamente esa nueva línea cuando la interfaz lo necesite.

texto = linecache.getline(ruta, numero).rstrip("\n")

No uses strip() indiscriminadamente porque elimina la indentación significativa.

Conserva la indentación

El whitespace muestra la estructura de bloques y afecta la sintaxis. Eliminarlo dificulta el diagnóstico y desalineará marcadores de columna.

Mantén la línea original y renderiza indicadores por separado.

Marcadores de columna

Linecache recupera texto, pero no interpreta offsets. SyntaxError, tokens y AST pueden proporcionar posiciones.

linea = linecache.getline(error.filename, error.lineno)
marcador = " " * (error.offset - 1) + "^"

Tabs, Unicode y offsets en bytes requieren cuidado. Usa tokenizer o AST para integración precisa con editores.

Muestra contexto cercano

Un diagnóstico puede incluir líneas antes y después.

def contexto(ruta, linea, radio=2):
    inicio = max(1, linea - radio)
    fin = linea + radio
    return [
        (numero, linecache.getline(ruta, numero))
        for numero in range(inicio, fin + 1)
    ]

Detén la salida al obtener valores vacíos más allá del archivo y limita el radio para reducir ruido.

Diagnósticos más claros

Linters y validadores pueden combinar filename, línea, columna, mensaje y fragmento.

config.py:18:7: valor inválido
    timeout = -1
          ^

No copies archivos completos a logs. Un contexto corto es más legible y seguro.

Seguridad de rutas

No aceptes una ruta arbitraria de usuario y la pases directamente a linecache. La función puede leer archivos accesibles por el proceso.

Restringe consultas a un workspace conocido, resuelve la ruta y confirma que el resultado permanece dentro de la raíz permitida.

from pathlib import Path

raiz = Path("proyecto").resolve()
objetivo = (raiz / ruta_usuario).resolve()
if objetivo != raiz and raiz not in objetivo.parents:
    raise ValueError("archivo fuera del proyecto")

Considera symlinks, permisos y cambios entre validación y lectura.

Privacidad

Las líneas de código pueden contener endpoints internos, nombres de clientes, consultas o secretos mal almacenados. Trata los fragmentos como datos sensibles.

Sanitiza informes enviados a servicios externos y aplica controles de acceso y retención.

Concurrencia

El cache es global al proceso. Las threads pueden consultar, pero invalidación y fuente mutable implican que el resultado no es un snapshot transaccional.

Para análisis consistente, lee el archivo una vez y conserva una copia inmutable propia.

Procesos separados

Cada proceso tiene su cache. Limpiar en el padre no afecta a los workers.

Los analizadores distribuidos deberían devolver diagnósticos compactos en lugar de asumir fuente compartida.

Uso de memoria

Analizar miles de archivos puede retener mucho texto. Llama a clearcache() al terminar un repositorio o lote.

Mide antes de optimizar: para tracebacks normales, el cache puede ser pequeño y útil.

Archivos enormes

Linecache está diseñado para fuente, no para consultas aleatorias sobre datasets gigantes. La carga puede mantener una lista completa de líneas.

Para logs enormes usa índices, seek, mmap o formatos de acceso aleatorio.

Archivos temporales

Si un archivo temporal se elimina después de entrar al cache, las consultas pueden seguir devolviendo líneas antiguas hasta una invalidación.

Esto puede preservar un traceback tardío, pero también confundir una herramienta que espera el filesystem actual.

Limitaciones de metadatos

La validación se basa en metadatos disponibles. Filesystems con resolución temporal baja, sincronización de red o sustituciones rápidas pueden producir casos inesperados.

Cuando la identidad exacta importa, usa paths de build inmutables o hashes en tu propia capa.

Notebooks y código interactivo

Los entornos interactivos generan filenames simbólicos y mantienen caches adicionales. Un nombre entre signos de menor y mayor puede no representar un archivo real.

Trata la disponibilidad del fuente como opcional en notebooks, REPLs y funciones dinámicas.

Integración con inspect

inspect.getsource() también depende de información de archivo y cache para recuperar funciones y clases.

Builtins, extensiones nativas y código generado pueden no tener fuente. Maneja la ausencia como resultado normal.

Integración con faulthandler

faulthandler produce pilas mínimas durante fallos graves. Después, las herramientas pueden usar linecache para enriquecer filenames y líneas cuando el fuente correspondiente existe.

Consulta faulthandler en Python.

Pruebas

Prueba primera y última línea, archivo ausente, número fuera del rango, encoding no UTF, archivo modificado, cache limpio, loader personalizado, módulo ZIP y ruta hostil.

Usa archivos temporales controlados y limpia el cache entre tests para evitar dependencia de orden.

No dependas de internals

El diccionario interno de cache existe, pero su formato exacto no es una API estable. Prefiere getline(), checkcache() y clearcache().

Aísla cualquier integración con fuente virtual y pruébala en cada versión soportada.

Cuándo leer directamente

Usa Path.read_text() o tokenize.open() cuando necesites todo el archivo, errores explícitos, snapshot inmutable o control completo de encoding.

Usa linecache para recuperar rápidamente una línea de diagnóstico.

Errores comunes

Los fallos frecuentes son usar índices desde cero, interpretar todo resultado vacío como línea vacía real, eliminar indentación, olvidar cache antiguo, aceptar rutas arbitrarias, usar el módulo para datos enormes y asumir que el fuente actual coincide con el código ejecutado.

Conclusión

linecache es una pieza pequeña pero esencial del diagnóstico de Python. Usa getline() para líneas puntuales, checkcache() cuando los archivos cambian y clearcache() después de lotes grandes.

Conserva indentación, protege paths y no trates el cache global como snapshot inmutable. Consulta la documentación oficial de linecache y tokenize en Python.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Contenido del artículo

    Artículos relacionados

    Código en un monitor que representa acceso a memoria nativa con ctypes.memoryview_at en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    ctypes.memoryview_at: memoria nativa sin copias

    Aprende ctypes.memoryview_at en Python para acceder a memoria nativa sin copias, validar punteros y reducir riesgos.

    Ler mais

    Tempo de leitura: 7 minutos
    12/10/2026
    Código Python en pantalla representando EnumDict y enumeraciones avanzadas
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    EnumDict: personaliza Enums con validación

    Aprende EnumDict en Python para personalizar EnumType, validar miembros y crear enumeraciones avanzadas con seguridad.

    Ler mais

    Tempo de leitura: 4 minutos
    11/10/2026
    Rack de servidores que representa el balanceo de conexiones con SO_REUSEPORT_LB en Python
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    SO_REUSEPORT_LB: reparte conexiones entre workers

    Aprende SO_REUSEPORT_LB en Python para distribuir conexiones entre workers con pruebas, portabilidad y cierre ordenado.

    Ler mais

    Tempo de leitura: 5 minutos
    11/10/2026
    Código Python asíncrono en un portátil para inspect.markcoroutinefunction
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    markcoroutinefunction: detecta wrappers async

    Aprende inspect.markcoroutinefunction en Python para identificar wrappers asíncronos, integrar frameworks y evitar detecciones incorrectas.

    Ler mais

    Tempo de leitura: 5 minutos
    10/10/2026
    Código Python para recorrer carpetas y archivos con Path.walk
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    Path.walk: recorre directorios con seguridad

    Aprende Path.walk en Python para recorrer directorios, filtrar archivos, tratar errores y controlar la travesía con seguridad.

    Ler mais

    Tempo de leitura: 5 minutos
    10/10/2026
    Depuración de un proceso Python en terminal con código
    Python Avanzado
    Foto de perfil de Leandro Hirt da Academify

    pdb -p: depura procesos Python en ejecución

    Aprende a conectar pdb a un proceso Python en ejecución, inspeccionar la pila y diagnosticar bloqueos de forma segura.

    Ler mais

    Tempo de leitura: 6 minutos
    09/10/2026