Dateiname und Zeilennummer des Python-Skripts


113

Wie kann ich den Dateinamen und die Zeilennummer im Python-Skript erhalten?

Genau die Dateiinformationen, die wir von einem Ausnahme-Traceback erhalten. In diesem Fall ohne Ausnahme.

Antworten:


161

Dank mcandre lautet die Antwort:

#python3
from inspect import currentframe, getframeinfo

frameinfo = getframeinfo(currentframe())

print(frameinfo.filename, frameinfo.lineno)

1
Hat die Verwendung dieser Methode Auswirkungen auf die Leistung (z. B. geringfügige Erhöhung der Laufzeit oder mehr benötigte CPU)?
Gsinha

6
@gsinha: Jeder Funktionsaufruf hat Auswirkungen auf die Leistung. Sie müssen messen, ob diese Auswirkungen für Sie akzeptabel sind.
Omikron

5
Also, wenn Sie Antworten vom Typ "einzeilig" mögen, verwenden Sie:import inspect inspect.getframeinfo(inspect.currentframe()).lineno
1-ijk

1
@LimokPalantaemon passiert, wenn currentframe()es aufgerufen wird, was bedeutet, dass Sie dies nicht mehr vereinfachen können als getframeinfo(currentframe()).lineno(wenn Sie sich nur um die Zeilennummer und nicht um den Dateinamen kümmern). Siehe docs.python.org/2/library/inspect.html#inspect.currentframe
Aaron Miller

1
@joey, sollte die print-Anweisung keine Klammern enthalten?
MCG

49

Ob Sie verwenden, currentframe().f_backhängt davon ab, ob Sie eine Funktion verwenden oder nicht.

Rufen Sie inspect direkt an:

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

Aufrufen einer Funktion, die dies für Sie erledigt:

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()

2
Plus eins, um eine Lösung in einer aufrufbaren Funktion bereitzustellen. Sehr schön!
MikeyE

21

Praktisch, wenn es in einer gemeinsamen Datei verwendet wird - druckt Dateiname, Zeilennummer und Funktion des Anrufers:

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

11

Dateiname :

__file__
# or
sys.argv[0]

Zeile :

inspect.currentframe().f_lineno

(nicht inspect.currentframe().f_back.f_linenowie oben erwähnt)


NameError: global name '__file__' is not definedauf meinem Python-Interpreter : Python 2.7.6 (default, Sep 26 2014, 15:59:23). Siehe stackoverflow.com/questions/9271464/…
bgoodr

10

Besser auch sys verwenden-

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

Die Ausgabe ist:

['__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

6

Nur um einen Beitrag zu leisten,

Es gibt ein linecacheModul in Python, hier sind zwei Links, die helfen können.

Dokumentation zum Linecache- Modul
Linecache-Quellcode

In gewisser Weise können Sie eine ganze Datei in ihren Cache "sichern" und sie mit linecache.cache-Daten aus der Klasse lesen.

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

Für zusätzliche Informationen, zur Fehlerbehandlung, können Sie einfach verwenden

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


3

In Python 3 können Sie eine Variation verwenden für:

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

Im Code können Sie dann verwenden:

Deb("Some useful information")
Deb()

Produzieren:

123: Some useful information
124:

Wobei die 123 und 124 die Leitungen sind, von denen aus die Anrufe getätigt werden.


0

Folgendes funktioniert für mich, um die Zeilennummer in Python 3.7.3 in VSCode 1.39.2 zu erhalten ( dmsgist meine Mnemonik für Debug- Meldungen ):

import inspect

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

So rufen Sie das Anzeigen einer Variablen name_sund ihres Werts auf:

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

Die Ausgabe sieht folgendermaßen aus:

37| name_s: value_of_variable_at_line_37
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.