nome do arquivo e número da linha do script python

113

Como posso obter o nome do arquivo e o número da linha no script python.

Exatamente as informações do arquivo que obtemos de um rastreamento de exceção. Nesse caso, sem gerar uma exceção.

Joey
fonte

Respostas:

161

Graças a mcandre, a resposta é:

#python3
from inspect import currentframe, getframeinfo

frameinfo = getframeinfo(currentframe())

print(frameinfo.filename, frameinfo.lineno)
Joey
fonte
1
O uso desse método tem algum impacto no desempenho (como um pequeno aumento no tempo de execução ou mais CPU necessária)?
gsinha 14/12/2014
6
@gsinha: Cada chamada de função tem impacto no desempenho. Você tem que medir se esse impacto é aceitável para você.
Omikron
5
Então, se você gosta de respostas do tipo "uma linha", use:import inspect inspect.getframeinfo(inspect.currentframe()).lineno
1-ijk
1
@LimokPalantaemon acontece quando currentframe()é chamado, o que significa que você não pode simplificar mais do que getframeinfo(currentframe()).lineno(se você só se preocupa com o número da linha e não com o nome do arquivo). Consulte docs.python.org/2/library/inspect.html#inspect.currentframe
Aaron Miller
1
@joey, não deveria haver parênteses na declaração de impressão?
MCG de
49

Se você usa currentframe().f_back depende se você está usando uma função ou não.

Chamando a inspeção diretamente:

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

Chamar uma função que faz isso por você:

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
fonte
2
Mais um, para fornecer uma solução em uma função chamável. Muito agradável!
MikeyE
21

Útil se usado em um arquivo comum - imprime o nome do arquivo, o número da linha e a função do chamador:

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

Nome do arquivo :

__file__
# or
sys.argv[0]

Linha :

inspect.currentframe().f_lineno

(não inspect.currentframe().f_back.f_linenoconforme mencionado acima)

arilou
fonte
NameError: global name '__file__' is not definedno meu interpretador Python: Python 2.7.6 (default, Sep 26 2014, 15:59:23). Consulte stackoverflow.com/questions/9271464/…
bgoodr
10

Melhor usar o sistema também-

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

O resultado é:

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

Só para contribuir,

existe um linecachemódulo em python, aqui estão dois links que podem ajudar.

documentação do módulo
linecache código-fonte do linecache

De certo modo, você pode "despejar" um arquivo inteiro em seu cache e lê-lo com os dados linecache.cache da classe.

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 obter informações adicionais, para tratamento de erros, você pode simplesmente usar

from sys import exc_info
try:
     raise YourError # or some other error
except Exception:
     print(exc_info() )
Danilo
fonte
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
fonte
Semelhante a __file__: Consulte stackoverflow.com/questions/3056048/…
bgoodr
3

No Python 3, você pode usar uma variação de:

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

No código, você pode usar:

Deb("Some useful information")
Deb()

Para produzir:

123: Some useful information
124:

Onde 123 e 124 são as linhas de onde as chamadas são feitas.

Thickycat
fonte
0

Aqui está o que funciona para mim para obter o número da linha em Python 3.7.3 em VSCode 1.39.2 ( dmsgé meu mnemônico para mensagem de depuração):

import inspect

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

Para chamar mostrando uma variável name_se seu valor:

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

A saída é semelhante a esta:

37| name_s: value_of_variable_at_line_37
Steph
fonte