Estou tentando aprender como funciona um aplicativo. E para isso estou inserindo comandos de depuração como a primeira linha do corpo de cada função com o objetivo de registrar o nome da função, bem como o número da linha (dentro do código) onde envio uma mensagem para a saída do log. Por fim, como este aplicativo é composto por muitos arquivos, desejo criar um único arquivo de log para poder entender melhor o fluxo de controle do aplicativo.
Aqui está o que eu sei:
para obter o nome da função, posso usar,
function_name.__name__
mas não quero usar o function_name (para que eu pudesse copiar e colar rapidamente um genéricoLog.info("Message")
no corpo de todas as funções). Eu sei que isso pode ser feito em C usando__func__
macro, mas não tenho certeza sobre python.para obter o nome do arquivo e o número da linha, vi que (e acredito que) meu aplicativo está usando a
locals()
função Python , mas em uma sintaxe que não conheço completamente, por exemplo:options = "LOG.debug('%(flag)s : %(flag_get)s' % locals())
e tentei usando likeLOG.info("My message %s" % locals())
que produz algo semelhante{'self': <__main__.Class_name object at 0x22f8cd0>}
. Alguma entrada sobre isso, por favor?Eu sei como usar o log e adicionar manipulador a ele para registrar em um arquivo, mas não tenho certeza se um único arquivo pode ser usado para registrar todas as mensagens de log na ordem correta das chamadas de função no projeto.
Eu apreciaria muito qualquer ajuda.
Obrigado!
import pdb; pdb.set_trace()
e, em seguida, percorrer o código de forma interativa. Isso pode ajudá-lo a rastrear o fluxo do programa.Respostas:
Você tem algumas perguntas marginalmente relacionadas aqui.
Vou começar com o mais fácil: (3). Usando,
logging
você pode agregar todas as chamadas a um único arquivo de log ou outro destino de saída: elas estarão na ordem em que ocorreram no processo.Em seguida: (2).
locals()
fornece um dicionário do escopo atual. Assim, em um método que não possui outros argumentos, você temself
no escopo, que contém uma referência à instância atual. O truque usado que o está deixando perplexo é a formatação da string usando um dict como o RHS do%
operador."%(foo)s" % bar
será substituído por qualquer que seja o valor debar["foo"]
.Finalmente, você pode usar alguns truques de introspecção, semelhantes aos usados por
pdb
que pode registrar mais informações:Isso registrará a mensagem passada, mais o nome da função (original), o nome do arquivo em que a definição aparece e a linha nesse arquivo. Dê uma olhada em inspect - Inspecione objetos ativos para obter mais detalhes.
Como mencionei em meu comentário anterior, você também pode entrar em um
pdb
prompt de depuração interativo a qualquer momento inserindo a linhaimport pdb; pdb.set_trace()
e executando novamente o programa. Isso permite que você percorra o código, inspecionando os dados conforme sua escolha.fonte
'%(foo)s : %(bar)s'
que também imprimiria obar["foo"]
valor de? Ou é um pouco diferente do seu exemplo?%(<foo>)s
é substituído pelo valor do objeto referenciado no dicionário<foo>
. Há mais exemplos / detalhes em docs.python.org/library/stdtypes.html#string-formattingA resposta correta para isso é usar a
funcName
variável já fornecidaEm seguida, em qualquer lugar que você quiser, basta adicionar:
Exemplo de saída de um script em que estou trabalhando agora:
fonte
getLogger(__name__)
logging.getLogger('root')
provavelmente não é o que você está esperando, não é oroot
logger, mas um logger comum com o nome 'root'.funcname
,linename
Elineno
fornecer informações sobre a última função que fez o registro.Se você tiver um wrapper de logger (por exemplo, singleton logger), a resposta de @sintesizerpatel pode não funcionar para você.
Para descobrir os outros chamadores na pilha de chamadas, você pode fazer:
fonte
logging
classes suportes pilha nível pular out-of-the-box: Métodos comolog()
,debug()
, etc. agora aceitar umstacklevel
argumento. Veja a documentação .