This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: linecache module returns wrong results
Type: behavior Stage: patch review
Components: Library (Lib) Versions: Python 3.0, Python 2.7, Python 2.6
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: Nosy List: RafeSacks, ajaksu2, diazona, exarkun, georg.brandl, gvanrossum, ndim, theller
Priority: normal Keywords: patch

Created on 2005-09-30 14:57 by theller, last changed 2022-04-11 14:56 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
linecache.patch theller, 2005-09-30 15:08
test_linecache.py ajaksu2, 2009-04-25 19:47 Tests for linecache, with this bug as a failure
basename.diff ajaksu2, 2009-04-25 20:16 Use 'filename' instead of 'os.path.split(filename)[1]'
Messages (13)
msg26463 - (view) Author: Thomas Heller (theller) * (Python committer) Date: 2005-09-30 14:57
On several occasions I have seen tracebacks in my code
pointing to PIL's __init__.py file. That is strange,
because I have installed PIL but it is used nowhere.

Finally I traced it down to a problem in the linecache
code, which tries to be smart in up updatecache
function.  When os.stat() on the filename fails with
os.error, it walks along sys.path and returns the first
file with a matching basename. This *may* make sense
for toplevel modules, but never for modules in packages.

So, if the traceback's stack contains an entry for a
non-existing file (for example because the .py file for
a .pyc file is no longer present), linecache returns
absolute garbage.

Example, on my system (the \a\b\c\__init__.py file
doesn't exist):

C:\>python -c "import linecache; print
linecache.getlines(r'\a\b\c\__init__.py')"
['#\n', '# The Python Imaging Library.\n',
'# $Id: //modules/pil/PIL/__init__.py#2 $\n', '#\n',
'# package placeholder\n', '#\n', '# Copyright (c) 1999
by Secret Labs AB.\n',
'#\n', '# See the README file for information on usage
and redistribution.\n',
'#\n', '\n', '# ;-)\n']
C:\>

The bug is present in 2.3, 2.4, and current CVS.
msg26464 - (view) Author: Thomas Heller (theller) * (Python committer) Date: 2005-09-30 15:08
Logged In: YES 
user_id=11105

The attached patch is a radical way to fix this problem - it
refuses to guess if the file is not found.
msg26465 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2005-09-30 16:24
Logged In: YES 
user_id=6380

Radical indeed. But what about the use case of modules
compiled on one system and moved to a different system? Is
that use case important enough?

There used to be a different use case, because bytecode
files used to contain relative path names. I believe that's
been fixed, if only by code in site.py that absolutizes
sys.path. (Except the initial '' -- is that important?)
msg26466 - (view) Author: Thomas Heller (theller) * (Python committer) Date: 2005-09-30 17:12
Logged In: YES 
user_id=11105

> But what about the use case of modules compiled on one system
> and moved to a different system? Is that use case important
> enough?

Maybe.  Couldn't the code be made more robust, so that it
works as intended with packages?  Unfortunately the code
objects don't have a reference to the module where they live
(probably because they are created before the module is
created).

BTW: The bug sometimes also is responsible for tracebacks in
pydoc, because it cannot locate the sourceline in the file.
 So, wrong sourec in tracebacks aren't the only problem.

It seems it would work better with relative pathnames, but
it's too late for that.
msg69034 - (view) Author: Hans Ulrich Niedermann (ndim) Date: 2008-07-01 00:28
The following issues appear to be the same bug to me:

   http://bugs.python.org/issue1068477
   http://bugs.python.org/issue1309567
   http://bugs.python.org/issue1754483

and are, as of 2008-06-30, unfixed in both rel25-maint and trunk.
msg70758 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2008-08-05 19:30
Is this still relevant?
msg70766 - (view) Author: Hans Ulrich Niedermann (ndim) Date: 2008-08-05 20:10
Unless someone has fixed it since 2008-07-05, it is still relevant.

I'll have to take a look at the current code first, though, to confirm
in either way.

There has been some discussion on this issue over at
http://bugs.python.org/issue1754483 but no complete resolution either.
msg75448 - (view) Author: Jean-Paul Calderone (exarkun) * (Python committer) Date: 2008-11-01 19:25
This is still relevant.  It makes linecache (and therefore some other
things, like inspect.getsource) almost useless in many cases.  For
example, because of this, sometimes inspect.getsource will raise an
IOError and sometimes it will return garbage data.  If the source file
isn't around, it'd be much better to fail all the time.  Rummaging
around in the filesystem hoping to get lucky and find another file with
the same name which contains the correct contents is insane.  This may
have made sense when relative path names were being used, but it makes
no sense anymore.
msg75952 - (view) Author: Rafe Sacks (RafeSacks) Date: 2008-11-17 07:58
This seems related to http://bugs.python.org/issue1218234 as well. 
This is my first bug report. I hope I do this right.
I posted this to comp.lang.python and was directed here. Here is a
chopped paste of that post:

I am getting an error on line 510 of inspect.py:

504    if iscode(object):
505        if not hasattr(object, 'co_firstlineno'):
506            raise IOError('could not find function definition')
507        lnum = object.co_firstlineno - 1
508        pat = re.compile(r'^(\s*def\s)|(.*(?<!\w)lambda(:|\s))|^(\s*@)')
509        while lnum > 0:
510            if pat.match(lines[lnum]): break
511            lnum = lnum - 1
512        return lines, lnum

I finally figured out that there was a caching problem. The function I
passed was changed, but the code lines (strings) retrieved by
linecache.getlines() (on lines 464 and 466) didn't update with the new
module contents... To get around this, I invoke linecache.clearcache()...

    linecache.clearcache()
    lines, n = inspect.getsourcelines(fn)


While inspect uses the cached module to get the text, the line number
used to find the block of source lines is retrieved from the passed
object. So, if I pass a function which reports that it starts on line
50, but in the cache it starts on line 40, an error isn't raised but the
lines of code returned are wrong. The error only occurs when the line
number is higher than the number of lines in the cached module.

Cheers,

- Rafe
msg79117 - (view) Author: David Zaslavsky (diazona) Date: 2009-01-05 09:59
I just had the same problem in a call to inspect.findsource() 
(actually my code calls inspect.stack() which calls ... which calls 
findsource()). The code object passed to findsource() had a filename 
of "database/__init__.py" which is the correct filename relative to 
sys.path, so in this case a simple fix would have worked: delete line 
82 of linecache.py
 82        basename = os.path.split(filename)[1]
and use filename instead of basename for the rest of the function. (Or 
for a quick hack, change line 82 to just "basename = filename")

I'm using Python 2.5.2 but the relevant code in linecache.py also 
exists in 3.0 (just checked).
msg86542 - (view) Author: Daniel Diniz (ajaksu2) * (Python triager) Date: 2009-04-25 19:47
Adding some tests to make working on a patch easier.
msg86545 - (view) Author: Daniel Diniz (ajaksu2) * (Python triager) Date: 2009-04-25 20:16
Patch (against py3k) with David Zaslavsky's solution from msg79117. It
would be good to find failing tests after it's applied so we can fix
this without breaking valid use cases.
msg87225 - (view) Author: Georg Brandl (georg.brandl) * (Python committer) Date: 2009-05-05 08:30
Applied patch and added test suite in r72319.
History
Date User Action Args
2022-04-11 14:56:13adminsetgithub: 42435
2009-05-05 08:30:46georg.brandlsetstatus: open -> closed

nosy: + georg.brandl
messages: + msg87225

resolution: fixed
2009-05-05 08:22:17georg.brandllinkissue1754483 superseder
2009-05-05 08:22:17georg.brandlunlinkissue1754483 dependencies
2009-05-05 08:21:17georg.brandllinkissue1068477 superseder
2009-05-05 08:21:17georg.brandlunlinkissue1068477 dependencies
2009-04-25 20:32:06ajaksu2linkissue1754483 dependencies
2009-04-25 20:29:05ajaksu2linkissue1068477 dependencies
2009-04-25 20:16:24ajaksu2setfiles: + basename.diff

messages: + msg86545
2009-04-25 19:47:29ajaksu2setfiles: + test_linecache.py

type: behavior
versions: - Python 2.5, Python 2.4, Python 2.3
keywords: + patch
nosy: + ajaksu2

messages: + msg86542
stage: patch review
2009-01-05 09:59:43diazonasetnosy: + diazona
messages: + msg79117
versions: + Python 3.0
2008-11-17 07:58:26RafeSackssetnosy: + RafeSacks
messages: + msg75952
2008-11-01 19:25:23exarkunsetnosy: + exarkun
messages: + msg75448
2008-08-05 20:10:29ndimsetmessages: + msg70766
2008-08-05 19:30:46gvanrossumsetmessages: + msg70758
2008-07-01 00:30:07ndimsetcomponents: + Library (Lib), - None
versions: + Python 2.6, Python 2.5, Python 2.4, Python 2.3, Python 2.7
2008-07-01 00:28:24ndimsetnosy: + ndim
messages: + msg69034
2005-09-30 14:57:17thellercreate