1. 程式人生 > 實用技巧 >豐富你的日誌資訊:從Python呼叫堆疊獲取行號等資訊

豐富你的日誌資訊:從Python呼叫堆疊獲取行號等資訊

程式中的日誌列印,或者訊息上傳,比如kafka訊息等等。經常上傳的訊息中需要上傳堆疊資訊中的檔名、行號、上層呼叫者等具體用於定位的訊息。Python提供了以下兩種方法:

  • sys._getframe, 基礎方法
  • inspect.currentframe, 推薦方法,提供除了sys._getframe方法之外更多的frame相關的方法

具體使用如下

使用sys._getframe私有方法

具體使用方法如下:

import os
import sys


def get_cur_info():
	"""
        獲取呼叫時的檔名,行號,上層呼叫者的名稱
        :return: 檔名,行號,上層呼叫者名稱
    """
	try:
		current_frame = sys._getframe(2)
		return os.path.basename(current_frame.f_code.co_filename), current_frame.f_lineno, current_frame.f_code.co_name
	except ValueError:
		return 'unknown', 0, 'unknown'

具體的函式輸出結果演示可以參見下面的inspect模組結果

使用inspect模組(推薦)

相比於sys的內建私有方法,更推薦inspect模組。inspect模組的具體使用方法如下

import os
import inspect

def get_cur_info():
	try:
		current_frame = inspect.currentframe(2)
		return os.path.basename(current_frame.f_code.co_filename), current_frame.f_lineno, current_frame.f_code.co_name
	except ValueError:
		return 'unknown', 0, 'unknown'


def produce():
	return get_cur_info()


def business():
	return produce()


if __name__ == '__main__':
	print(get_cur_info())  # 輸出 ('unknown', 0, 'unknown')

	print(produce())  # 輸出 ('a.py', 22, '<module>')

	print(business())  # 輸出 ('a.py', 16, 'business')

主要依賴inspect.currentframe方法,關於inspect.currentframe方法的使用見幫助文件

>>> help(inspect.currentframe)
Help on built-in function _getframe in module sys:

_getframe(...)
    _getframe([depth]) -> frameobject
    
    Return a frame object from the call stack.  If optional integer depth is
    given, return the frame object that many calls below the top of the stack.
    If that is deeper than the call stack, ValueError is raised.  The default
    for depth is zero, returning the frame at the top of the call stack.
    
    This function should be used for internal and specialized
    purposes only.

從呼叫堆疊返回一個幀物件。深度為整數,預設為0,返回呼叫堆疊頂部的幀。如果指定深度比呼叫堆疊深,會丟擲ValueError異常。該功能應該只用於內部和專業目的。

inspect.currentframe方法的實現見內建庫inspect.py

if hasattr(sys, '_getframe'):
    currentframe = sys._getframe
else:
    currentframe = lambda _=None: None

所以本質上inspect.currentframe方法等同於sys._getframe方法

currentframe = lambda _=None: None 等同於 currentframe = lambda _: None ,即lambda函式接收一個引數,返回None


參考:

  1. Python frame hack

  2. StackOverFlow-In Python, how do I obtain the current frame?


記得幫我點贊哦!

精心整理了計算機各個方向的從入門、進階、實戰的視訊課程和電子書,按照目錄合理分類,總能找到你需要的學習資料,還在等什麼?快去關注下載吧!!!

念念不忘,必有迴響,小夥伴們幫我點個贊吧,非常感謝。

我是職場亮哥,YY高階軟體工程師、四年工作經驗,拒絕鹹魚爭當龍頭的斜槓程式設計師。

聽我說,進步多,程式人生一把梭

如果有幸能幫到你,請幫我點個【贊】,給個關注,如果能順帶評論給個鼓勵,將不勝感激。

職場亮哥文章列表:更多文章

本人所有文章、回答都與版權保護平臺有合作,著作權歸職場亮哥所有,未經授權,轉載必究!