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.

Joey
quelle

Antworten:

161

Dank mcandre lautet die Antwort:

#python3
from inspect import currentframe, getframeinfo

frameinfo = getframeinfo(currentframe())

print(frameinfo.filename, frameinfo.lineno)
Joey
quelle
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()
aaren
quelle
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])
Streamsoup
quelle
11

Dateiname :

__file__
# or
sys.argv[0]

Zeile :

inspect.currentframe().f_lineno

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

Arilou
quelle
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
Mohammad Shahid Siddiqui
quelle
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() )
Danilo
quelle
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
quelle
Ähnlich wie __file__: Siehe stackoverflow.com/questions/3056048/…
bgoodr
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.

Dickkatze
quelle
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
Steph
quelle