python中使用sys模板和logging模块获取行号和函数名的方法


Posted in Python onApril 15, 2014

对于python,这几天一直有两个问题在困扰我:
1.python中没办法直接取得当前的行号和函数名。这是有人在论坛里提出的问题,底下一群人只是在猜测python为什么不像__file__一样提供__line__和__func__,但是却最终也没有找到解决方案。
2.如果一个函数在不知道自己名字的情况下,怎么才能递归调用自己。这是我一个同事问我的,其实也是获取函数名,但是当时也是回答不出来。

但是今晚!所有的问题都有了答案。
一切还要从我用python的logging模块说起,logging中的format中是有如下选项的:

%(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是能够获取到调用者的行号和函数名的,那会不会也可以获取到自己的行号和函数名呢?
我们来看一下源码,主要部分如下:

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)

我简单解释一下,实际上是通过在currentframe函数中抛出一个异常,然后通过向上查找的方式,找到调用的信息。其中

rv = (co.co_filename, f.f_lineno, co.co_name)

的三个值分别为文件名,行号,函数名。(可以去http://docs.python.org/library/sys.html来看一下代码中几个系统函数的说明)
OK,如果已经看懂了源码,那获取当前位置的行号和函数名相信也非常清楚了,代码如下:

#!/usr/bin/python
# -*- coding: utf-8 -*-
'''
#=============================================================================
#  FileName:        xf.py
#  Description:     获取当前位置的行号和函数名
#  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()

输入结果是:
('callfunc', 24)

符合预期~~
哈哈,OK!现在应该不用再抱怨取不到行号和函数名了吧~

=============================================================================
后来发现,其实也可以有更简单的方法,如下:

import sys
def get_cur_info():
    print sys._getframe().f_code.co_name
    print sys._getframe().f_back.f_code.co_name
get_cur_info()

调用结果是:
get_cur_info
<module>
Python 相关文章推荐
35个Python编程小技巧
Apr 01 Python
python新手经常遇到的17个错误分析
Jul 30 Python
Python2.x中文乱码问题解决方法
Jun 02 Python
python中format()函数的简单使用教程
Mar 14 Python
教你使用python实现微信每天给女朋友说晚安
Mar 23 Python
python利用requests库进行接口测试的方法详解
Jul 06 Python
使用Flask-Cache缓存实现给Flask提速的方法详解
Jun 11 Python
Python 多个图同时在不同窗口显示的实现方法
Jul 07 Python
PyTorch中permute的用法详解
Dec 30 Python
在服务器上安装python3.8.2环境的教程详解
Apr 26 Python
python如何调用字典的key
May 25 Python
python按顺序重命名文件并分类转移到各个文件夹中的实现代码
Jul 21 Python
python 动态获取当前运行的类名和函数名的方法
Apr 15 #Python
python使用百度翻译进行中翻英示例
Apr 14 #Python
python使用xauth方式登录饭否网然后发消息
Apr 11 #Python
python判断、获取一张图片主色调的2个实例
Apr 10 #Python
Python使用新浪微博API发送微博的例子
Apr 10 #Python
一个检测OpenSSL心脏出血漏洞的Python脚本分享
Apr 10 #Python
Python删除指定目录下过期文件的2个脚本分享
Apr 10 #Python
You might like
PHP 全角转半角实现代码
2010/05/16 PHP
JS图像无缝滚动脚本非常好用
2014/02/10 Javascript
node.js中的http.response.writeHead方法使用说明
2014/12/14 Javascript
javascript上下方向键控制表格行选中并高亮显示的方法
2015/02/13 Javascript
JavaScript中eval()函数用法详解
2015/12/14 Javascript
举例讲解如何判断JavaScript中对象的类型
2016/04/22 Javascript
Javascript发送AJAX请求实例代码
2016/08/21 Javascript
jQuery使用unlock.js插件实现滑动解锁
2017/04/04 jQuery
socket.io学习教程之基本应用(二)
2017/04/29 Javascript
jquery拖动改变div大小
2017/07/04 jQuery
Angular2关于@angular/cli默认端口号配置的问题
2017/07/15 Javascript
JavaScript实现公告栏上下滚动效果
2020/03/13 Javascript
vue v-on:click传递动态参数的步骤
2020/09/11 Javascript
详解Vue的mixin策略
2020/11/19 Vue.js
Python3.x中自定义比较函数
2015/04/24 Python
Python 实现购物商城,含有用户入口和商家入口的示例
2017/09/15 Python
Python实现PS图像调整颜色梯度效果示例
2018/01/25 Python
Python Grid使用和布局详解
2018/06/30 Python
使用python绘制二元函数图像的实例
2019/02/12 Python
python3利用ctypes传入一个字符串类型的列表方法
2019/02/12 Python
三步实现Django Paginator分页的方法
2019/06/11 Python
python爬虫 基于requests模块的get请求实现详解
2019/08/20 Python
python解包概念及实例
2021/02/17 Python
使用Filters滤镜弥补CSS3的跨浏览器问题以及兼容低版本IE
2013/01/23 HTML / CSS
布局和排版教程 纯css3实现图片三角形排列
2014/10/17 HTML / CSS
台湾网购生鲜第一品牌:i3Fresh爱上新鲜
2017/10/26 全球购物
台湾全方位线上课程与职能学习平台:TibaMe
2019/12/04 全球购物
物流专业大学生职业生涯规划书范文
2014/01/15 职场文书
留学推荐信怎么写
2014/01/25 职场文书
最新会计专业求职信范文
2014/01/28 职场文书
优良学风班申请材料
2014/02/13 职场文书
国防教育标语
2014/10/08 职场文书
经理助理岗位职责
2015/02/02 职场文书
高三教师工作总结2015
2015/07/21 职场文书
正确使用MySQL update语句
2021/05/26 MySQL
mybatis-plus模糊查询指定字段
2022/04/28 Java/Android