nombre de archivo y número de línea de la secuencia de comandos de Python

113

¿Cómo puedo obtener el nombre del archivo y el número de línea en el script de Python?

Exactamente la información de archivo que obtenemos de un rastreo de excepción. En este caso sin plantear una excepción.

Joey
fuente

Respuestas:

161

Gracias a mcandre, la respuesta es:

#python3
from inspect import currentframe, getframeinfo

frameinfo = getframeinfo(currentframe())

print(frameinfo.filename, frameinfo.lineno)
Joey
fuente
1
¿El uso de este método tiene algún impacto en el rendimiento (como un aumento menor en el tiempo de ejecución o más CPU necesaria)?
gsinha
6
@gsinha: cada llamada a función tiene un impacto en el rendimiento. Tienes que medir si este impacto es aceptable para ti.
omikron
5
Por lo tanto, si le gustan las respuestas de tipo "una línea", use:import inspect inspect.getframeinfo(inspect.currentframe()).lineno
1-ijk
1
@LimokPalantaemon sucede cuando currentframe()se llama, lo que significa que no puede simplificar esto más que getframeinfo(currentframe()).lineno(si solo le importa el número de línea y no el nombre del archivo). Ver docs.python.org/2/library/inspect.html#inspect.currentframe
Aaron Miller
1
@joey, ¿no debería haber paréntesis en la declaración impresa?
MCG
49

El uso currentframe().f_backdepende de si está utilizando una función o no.

Llamar a inspeccionar directamente:

from inspect import currentframe, getframeinfo

cf = currentframe()
filename = getframeinfo(cf).filename

print "This is line 5, python says line ", cf.f_lineno 
print "The filename is ", filename

Llamar a una función que lo hace por ti:

from inspect import currentframe

def get_linenumber():
    cf = currentframe()
    return cf.f_back.f_lineno

print "This is line 7, python says line ", get_linenumber()
aaren
fuente
2
Más uno, por proporcionar una solución en una función invocable. ¡Muy agradable!
MikeyE
21

Útil si se usa en un archivo común: imprime el nombre del archivo, el número de línea y la función de la persona que llama:

import inspect
def getLineInfo():
    print(inspect.stack()[1][1],":",inspect.stack()[1][2],":",
          inspect.stack()[1][3])
Streamsoup
fuente
11

Nombre de archivo :

__file__
# or
sys.argv[0]

Línea :

inspect.currentframe().f_lineno

(no inspect.currentframe().f_back.f_linenocomo se mencionó anteriormente)

arilou
fuente
NameError: global name '__file__' is not defineden mi intérprete de Python: Python 2.7.6 (default, Sep 26 2014, 15:59:23). Ver stackoverflow.com/questions/9271464/…
bgoodr
10

Es mejor usar sys también

print dir(sys._getframe())
print dir(sys._getframe().f_lineno)
print sys._getframe().f_lineno

La salida es:

['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'f_back', 'f_builtins', 'f_code', 'f_exc_traceback', 'f_exc_type', 'f_exc_value', 'f_globals', 'f_lasti', 'f_lineno', 'f_locals', 'f_restricted', 'f_trace']
['__abs__', '__add__', '__and__', '__class__', '__cmp__', '__coerce__', '__delattr__', '__div__', '__divmod__', '__doc__', '__float__', '__floordiv__', '__format__', '__getattribute__', '__getnewargs__', '__hash__', '__hex__', '__index__', '__init__', '__int__', '__invert__', '__long__', '__lshift__', '__mod__', '__mul__', '__neg__', '__new__', '__nonzero__', '__oct__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdiv__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', '__xor__', 'bit_length', 'conjugate', 'denominator', 'imag', 'numerator', 'real']
14
Mohammad Shahid Siddiqui
fuente
6

Solo para contribuir

hay un linecachemódulo en Python, aquí hay dos enlaces que pueden ayudar.

documentación del módulo
linecache código fuente de linecache

En cierto sentido, puede "volcar" un archivo completo en su caché y leerlo con los datos linecache.cache de la clase.

import linecache as allLines
## have in mind that fileName in linecache behaves as any other open statement, you will need a path to a file if file is not in the same directory as script
linesList = allLines.updatechache( fileName ,None)
for i,x in enumerate(lineslist): print(i,x) #prints the line number and content
#or for more info
print(line.cache)
#or you need a specific line
specLine = allLines.getline(fileName,numbOfLine)
#returns a textual line from that number of line

Para obtener información adicional, para el manejo de errores, simplemente puede usar

from sys import exc_info
try:
     raise YourError # or some other error
except Exception:
     print(exc_info() )
Danilo
fuente
5
import inspect    

file_name = __FILE__
current_line_no = inspect.stack()[0][2]
current_function_name = inspect.stack()[0][3]

#Try printing inspect.stack() you can see current stack and pick whatever you want 
Haroon Rashedu
fuente
Similar a __file__: Ver stackoverflow.com/questions/3056048/…
bgoodr
3

En Python 3 puedes usar una variación de:

def Deb(msg = None):
  print(f"Debug {sys._getframe().f_back.f_lineno}: {msg if msg is not None else ''}")

En código, puede usar:

Deb("Some useful information")
Deb()

Para producir:

123: Some useful information
124:

Donde 123 y 124 son las líneas desde las que se realizan las llamadas.

Thickycat
fuente
0

Esto es lo que me funciona para obtener el número de línea en Python 3.7.3 en VSCode 1.39.2 ( dmsges mi mnemónico para el mensaje de depuración):

import inspect

def dmsg(text_s):
    print (str(inspect.currentframe().f_back.f_lineno) + '| ' + text_s)

Para llamar mostrando una variable name_sy su valor:

name_s = put_code_here
dmsg('name_s: ' + name_s)

La salida se ve así:

37| name_s: value_of_variable_at_line_37
Steph
fuente