Skip to main content

Lib/linecache.py

Source:

cpython 3.14 @ ab2d84fe1023/Lib/linecache.py

linecache caches Python source files line by line for traceback display and the inspect module. It also handles <string> (exec'd code) and zip-file sources.

Map​

LinesSymbolRole
1-40Module-level cache dict{filename: (size, mtime, lines, fullname)}
41-80getlineReturn a single line (1-based)
81-140getlines, updatecacheRead and cache a file
141-180checkcache, clearcache, lazycacheCache management

Reading​

getline​

# CPython: Lib/linecache.py:26 getline
def getline(filename, lineno, module_globals=None):
lines = getlines(filename, module_globals)
if 1 <= lineno <= len(lines):
return lines[lineno - 1]
return ''

Traceback formatting calls getline(filename, lineno) for every frame to display the source context.

updatecache​

# CPython: Lib/linecache.py:98 updatecache
def updatecache(filename, module_globals=None):
# Try the filesystem first
try:
stat = os.stat(fullname)
except OSError:
pass
else:
size, mtime = stat.st_size, stat.st_mtime
with tokenize.open(fullname) as fp:
lines = fp.readlines()
cache[filename] = size, mtime, lines, fullname
return lines
# Fall back to linecache_loader hooks (for zip imports, frozen modules, etc.)
if module_globals and '__loader__' in module_globals:
loader = module_globals['__loader__']
...
source = loader.get_source(module_globals['__name__'])
if source:
lines = source.splitlines(keepends=True)
cache[filename] = (len(source), None, lines, filename)
return lines
return []

The loader fallback handles .pyc-only distributions where the .py source is not on disk.

checkcache​

# CPython: Lib/linecache.py:68 checkcache
def checkcache(filename=None):
if filename is None:
filenames = list(cache.keys())
else:
filenames = [filename]
for fn in filenames:
info = cache.get(fn)
if info and len(info) != 1: # skip lazycache entries (len==1)
size, mtime, lines, fullname = info
if mtime is None:
continue # dynamically loaded, can't check
try:
stat = os.stat(fullname)
except OSError:
cache.pop(fn, None)
else:
if size != stat.st_size or mtime != stat.st_mtime:
cache.pop(fn, None)

Called by the interactive interpreter between commands so edited source files show up correctly in tracebacks.

gopy notes​

linecache is used by traceback, inspect, and pdb. In gopy it is needed for accurate traceback display. The module can be ported as-is since it only uses os, tokenize, and sys, all of which gopy implements. The loader-based fallback is important for frozen stdlib modules.