File name and line number

Alex Martelli aleaxit at yahoo.com
Fri Aug 10 21:31:14 CEST 2001


[Posted and mailed, as requested]

"Marielle Fois" <im99_foa at nada.kth.se> wrote in message
news:Pine.SOL.4.30.0108102017490.22519-100000 at my.nada.kth.se...
> Hello,
>
> Is is possible to know the name of a python file within the file
> itself? And the line number of the instruction that is currently
> being executed?


When a Python module is imported, Python sets its __file__
attribute to the filename of the file it was imported from.

If you're talking about a module rather than a main script,
this should suffice for your 'name of a python file' request.

Do note that the *directory* part of the name may differ
(you may use the functions in module os.path to normalize
and/or analize it, of course).

For more generality you need function _getframe of module
sys.  As the leading _ indicates, it's a "delicate" function,
meant to be used only for very special purposes -- getting
filename and linenumber presumably meet the "very special"
test, being a typical task of a development/debugging
framework rather than of normal programs.

sys._getframe() returns the frame object it was called
from (you can get the caller's frame, the caller's caller's
frame, etc, by passing _getframe a numeric argument:
default is 0, 1 means caller's frame, and so on).

One of the attributes of a frame object is f_lineno, which
gets incremented (in a non-optimized Python run, only;
i.e., if Python was *NOT* started with option -O or -OO!)
by a special bytecode operation so it always reflects the
current linenumber in the execution frame.  For example,
save the following to file lino.py:

import sys
x = sys._getframe()
print 'line',x.f_lineno
print 'line',x.f_lineno
print 'line',x.f_lineno

and run it:

D:\Python21>python lino.py
line 3
line 4
line 5

However, if you optimize, it's not that useful any more:

D:\Python21>python -O lino.py
line 1
line 1
line 1

but them's the breaks -- no line-numbers from optimized
bytecode (you only optimize when you're finished doing
development and debugging, anyway).


For the filename, add one last line to the above script:
print 'file',x.f_code.co_filename
and now running it you get:

D:\Python21>python lino.py
line 3
line 4
line 5
file lino.py

(the filename information remains even with -O).


> Suppose I have a function, and I want this function
> to take two arguments, first the name of the file where it is placed,
> and second at which line number. Is there any way of doing this?

This is a different question, of course -- you're asking not
what file is currently executing or on what line, but in what
file is a given function, and at what line (so you can pass
this info as arguments to the same function -- peculiar
but doable).  If x is any reference to the function, e.g.
    from amodule import afunction as x
or whatever, then:
    x.func_code.co_filename is the filename,
    x.func_code.co_firstlineno is the first line number
        (i.e., the 'def' line).

So, calling:
    x(x.func_code.co_filename,x.func_code.co_firstlineno)
should satisfy your peculiar request.  By the way, this
is not affected by -O or -OO being in use.


Alex






More information about the Python-list mailing list