The linecache module reads lines from files with caching. Get any line by number without reading the whole file repeatedly.

Basic Usage

import linecache
 
# Get specific line (1-indexed)
line = linecache.getline('script.py', 10)
print(line)  # Line 10 of script.py
 
# Returns empty string if line doesn't exist
line = linecache.getline('script.py', 9999)
print(repr(line))  # ''

How It Works

import linecache
 
# First call: reads and caches entire file
line1 = linecache.getline('data.txt', 1)
 
# Subsequent calls: returns from cache
line2 = linecache.getline('data.txt', 2)
line3 = linecache.getline('data.txt', 3)
 
# Much faster than repeatedly opening the file

Cache Management

import linecache
 
# Clear cache for specific file
linecache.checkcache('data.txt')
 
# Clear entire cache
linecache.clearcache()
 
# Update cache if file changed
linecache.updatecache('data.txt')

Get All Lines

import linecache
 
# Get all lines (list)
lines = linecache.getlines('data.txt')
print(f"File has {len(lines)} lines")
 
# Lines include newline characters
for i, line in enumerate(lines, 1):
    print(f"{i}: {line}", end='')

Reading from Modules

import linecache
import os
 
# Read line from a module's source
line = linecache.getline(os.__file__, 1)
print(line)  # First line of os.py

Practical Examples

Error Context Display

import linecache
 
def show_error_context(filename, lineno, context=3):
    """Show lines around an error."""
    print(f"Error at {filename}:{lineno}")
    print("-" * 40)
    
    start = max(1, lineno - context)
    end = lineno + context + 1
    
    for n in range(start, end):
        line = linecache.getline(filename, n)
        if not line:
            break
        marker = ">>>" if n == lineno else "   "
        print(f"{marker} {n:4d}: {line}", end='')
 
show_error_context('script.py', 42)

Custom Traceback Formatter

import linecache
import traceback
import sys
 
def format_exception_with_context():
    exc_type, exc_value, exc_tb = sys.exc_info()
    
    print(f"Exception: {exc_type.__name__}: {exc_value}")
    print()
    
    for frame in traceback.extract_tb(exc_tb):
        filename, lineno, name, _ = frame
        print(f"  File {filename}, line {lineno}, in {name}")
        
        # Show surrounding lines
        for n in range(lineno - 1, lineno + 2):
            line = linecache.getline(filename, n)
            if line:
                prefix = ">" if n == lineno else " "
                print(f"    {prefix} {line}", end='')
        print()

Log File Analysis

import linecache
 
def get_log_entries(logfile, line_numbers):
    """Get specific log entries by line number."""
    entries = []
    for n in line_numbers:
        line = linecache.getline(logfile, n)
        if line:
            entries.append((n, line.rstrip()))
    return entries
 
# Get lines 100, 200, 300
entries = get_log_entries('app.log', [100, 200, 300])
for lineno, text in entries:
    print(f"Line {lineno}: {text}")

Source Code Viewer

import linecache
 
def view_function_source(func):
    """Display source code of a function."""
    import inspect
    
    try:
        filename = inspect.getfile(func)
        lines, start = inspect.getsourcelines(func)
    except (TypeError, OSError):
        return "Source not available"
    
    output = []
    for i, line in enumerate(lines, start):
        output.append(f"{i:4d}: {line}")
    
    return "".join(output)

Diff Two Files

import linecache
 
def compare_lines(file1, file2, line_numbers):
    """Compare specific lines between two files."""
    differences = []
    
    for n in line_numbers:
        line1 = linecache.getline(file1, n).rstrip()
        line2 = linecache.getline(file2, n).rstrip()
        
        if line1 != line2:
            differences.append({
                'line': n,
                'file1': line1,
                'file2': line2,
            })
    
    return differences

Memory Considerations

import linecache
 
# linecache keeps files in memory
# Clear when done with large files
linecache.getlines('huge_file.txt')
# ... process lines ...
linecache.clearcache()  # Free memory

linecache vs Other Methods

# linecache: cached, random access
linecache.getline('file.txt', 50)
 
# readlines: load all into list
with open('file.txt') as f:
    lines = f.readlines()
    line = lines[49]
 
# enumerate: sequential access
with open('file.txt') as f:
    for i, line in enumerate(f, 1):
        if i == 50:
            break
MethodUse Case
linecacheRepeated random access
readlines()Process all lines, modify
enumerate()Sequential, memory efficient
islice()Get range of lines

Quick Reference

import linecache
 
# Get single line (1-indexed)
linecache.getline(filename, lineno)
 
# Get all lines
linecache.getlines(filename)
 
# Cache management
linecache.checkcache(filename)   # Refresh if changed
linecache.updatecache(filename)  # Force update
linecache.clearcache()           # Clear all
 
# Returns
# - Line with newline if exists
# - Empty string '' if not

linecache is used internally by the traceback module. When you need random access to file lines with caching, it's the right tool.

React to this post: