python中使用sys模板和logging模塊獲取行號(hào)和函數(shù)名的方法
對(duì)于python,這幾天一直有兩個(gè)問題在困擾我:
1.python中沒辦法直接取得當(dāng)前的行號(hào)和函數(shù)名。這是有人在論壇里提出的問題,底下一群人只是在猜測(cè)python為什么不像__file__一樣提供__line__和__func__,但是卻最終也沒有找到解決方案。
2.如果一個(gè)函數(shù)在不知道自己名字的情況下,怎么才能遞歸調(diào)用自己。這是我一個(gè)同事問我的,其實(shí)也是獲取函數(shù)名,但是當(dāng)時(shí)也是回答不出來。
但是今晚!所有的問題都有了答案。
一切還要從我用python的logging模塊說起,logging中的format中是有如下選項(xiàng)的:
%(name)s Name of the logger (logging channel)
%(levelno)s Numeric logging level for the message (DEBUG, INFO,
WARNING, ERROR, CRITICAL)
%(levelname)s Text logging level for the message ("DEBUG", "INFO",
"WARNING", "ERROR", "CRITICAL")
%(pathname)s Full pathname of the source file where the logging
call was issued (if available)
%(filename)s Filename portion of pathname
%(module)s Module (name portion of filename)
%(lineno)d Source line number where the logging call was issued
(if available)
%(funcName)s Function name
%(created)f Time when the LogRecord was created (time.time()
return value)
%(asctime)s Textual time when the LogRecord was created
%(msecs)d Millisecond portion of the creation time
%(relativeCreated)d Time in milliseconds when the LogRecord was created,
relative to the time the logging module was loaded
(typically at application startup time)
%(thread)d Thread ID (if available)
%(threadName)s Thread name (if available)
%(process)d Process ID (if available)
%(message)s The result of record.getMessage(), computed just as
the record is emitted
也就是說,logging是能夠獲取到調(diào)用者的行號(hào)和函數(shù)名的,那會(huì)不會(huì)也可以獲取到自己的行號(hào)和函數(shù)名呢?
我們來看一下源碼,主要部分如下:
def currentframe():
"""Return the frame object for the caller's stack frame."""
try:
raise Exception
except:
return sys.exc_info()[2].tb_frame.f_back
def findCaller(self):
"""
Find the stack frame of the caller so that we can note the source
file name, line number and function name.
"""
f = currentframe()
#On some versions of IronPython, currentframe() returns None if
#IronPython isn't run with -X:Frames.
if f is not None:
f = f.f_back
rv = "(unknown file)", 0, "(unknown function)"
while hasattr(f, "f_code"):
co = f.f_code
filename = os.path.normcase(co.co_filename)
if filename == _srcfile:
f = f.f_back
continue
rv = (co.co_filename, f.f_lineno, co.co_name)
break
return rv
def _log(self, level, msg, args, exc_info=None, extra=None):
"""
Low-level logging routine which creates a LogRecord and then calls
all the handlers of this logger to handle the record.
"""
if _srcfile:
#IronPython doesn't track Python frames, so findCaller throws an
#exception on some versions of IronPython. We trap it here so that
#IronPython can use logging.
try:
fn, lno, func = self.findCaller()
except ValueError:
fn, lno, func = "(unknown file)", 0, "(unknown function)"
else:
fn, lno, func = "(unknown file)", 0, "(unknown function)"
if exc_info:
if not isinstance(exc_info, tuple):
exc_info = sys.exc_info()
record = self.makeRecord(self.name, level, fn, lno, msg, args, exc_info, func, extra)
self.handle(record)
我簡單解釋一下,實(shí)際上是通過在currentframe函數(shù)中拋出一個(gè)異常,然后通過向上查找的方式,找到調(diào)用的信息。其中
rv = (co.co_filename, f.f_lineno, co.co_name)
的三個(gè)值分別為文件名,行號(hào),函數(shù)名。(可以去http://docs.python.org/library/sys.html來看一下代碼中幾個(gè)系統(tǒng)函數(shù)的說明)
OK,如果已經(jīng)看懂了源碼,那獲取當(dāng)前位置的行號(hào)和函數(shù)名相信也非常清楚了,代碼如下:
#!/usr/bin/python
# -*- coding: utf-8 -*-
'''
#=============================================================================
# FileName: xf.py
# Description: 獲取當(dāng)前位置的行號(hào)和函數(shù)名
# Version: 1.0
#=============================================================================
'''
import sys
def get_cur_info():
"""Return the frame object for the caller's stack frame."""
try:
raise Exception
except:
f = sys.exc_info()[2].tb_frame.f_back
return (f.f_code.co_name, f.f_lineno)
def callfunc():
print get_cur_info()
if __name__ == '__main__':
callfunc()
輸入結(jié)果是:
符合預(yù)期~~
哈哈,OK!現(xiàn)在應(yīng)該不用再抱怨取不到行號(hào)和函數(shù)名了吧~
=============================================================================
后來發(fā)現(xiàn),其實(shí)也可以有更簡單的方法,如下:
def get_cur_info():
print sys._getframe().f_code.co_name
print sys._getframe().f_back.f_code.co_name
get_cur_info()
調(diào)用結(jié)果是:
<module>
相關(guān)文章
numpy中np.nditer、flags=[multi_index] 的用法說明
這篇文章主要介紹了numpy中np.nditer、flags=['multi_index'] 的用法說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2021-05-05Linux-ubuntu16.04 Python3.5配置OpenCV3.2的方法
下面小編就為大家分享一篇Linux-ubuntu16.04 Python3.5配置OpenCV3.2的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-04-04python十進(jìn)制轉(zhuǎn)二進(jìn)制的詳解
在本篇文章里小編給大家整理了關(guān)于python十進(jìn)制轉(zhuǎn)二進(jìn)制的相關(guān)知識(shí)點(diǎn)內(nèi)容,需要的朋友們可以參考學(xué)習(xí)下。2020-02-02如何使用PyCharm將代碼上傳到GitHub上(圖文詳解)
這篇文章主要介紹了如何使用PyCharm將代碼上傳到GitHub上(圖文詳解),文中通過圖文介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-04-04Python實(shí)現(xiàn)字典按key或者value進(jìn)行排序操作示例【sorted】
這篇文章主要介紹了Python實(shí)現(xiàn)字典按key或者value進(jìn)行排序操作,結(jié)合實(shí)例形式分析了Python針對(duì)字典按照key或者value進(jìn)行排序的相關(guān)操作技巧,需要的朋友可以參考下2019-05-05