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 相关文章推荐
python通过伪装头部数据抵抗反爬虫的实例
May 07 Python
详解Django中类视图使用装饰器的方式
Aug 12 Python
浅谈Scrapy网络爬虫框架的工作原理和数据采集
Feb 07 Python
Django缓存系统实现过程解析
Aug 02 Python
PyQt Qt Designer工具的布局管理详解
Aug 07 Python
使用Windows批处理和WMI设置Python的环境变量方法
Aug 14 Python
通过 Django Pagination 实现简单分页功能
Nov 11 Python
通过实例简单了解Python中yield的作用
Dec 11 Python
python访问hdfs的操作
Jun 06 Python
Python matplotlib 绘制双Y轴曲线图的示例代码
Jun 12 Python
Python3读写ini配置文件的示例
Nov 06 Python
Python List remove()实例用法详解
Aug 02 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
声音就能俘获人心,蕾姆,是哪个漂亮小姐姐配音呢?
2020/03/03 日漫
php类
2006/11/27 PHP
ZF等常用php框架中存在的问题
2008/01/10 PHP
PHP iconv 解决utf-8和gb2312编码转换问题
2010/04/12 PHP
PHP以指定字段为索引返回数据库所取的数据数组
2013/06/30 PHP
一张表搞清楚php is_null、empty、isset的区别
2015/07/07 PHP
详解PHP中的Traits
2015/07/29 PHP
PHP7之Mongodb API使用详解
2015/12/26 PHP
基于JQuery的asp.net树实现代码
2010/11/30 Javascript
jQuery LigerUI 插件介绍及使用之ligerDrag和ligerResizable示例代码打包
2011/04/06 Javascript
jquery插件jquery.confirm弹出确认消息
2015/12/22 Javascript
基于jQuery实现淡入淡出效果轮播图
2020/07/31 Javascript
AngularJS学习笔记(三)数据双向绑定的简单实例
2016/11/08 Javascript
浅谈使用mpvue开发小程序需要注意和了解的知识点
2018/05/23 Javascript
使用elementUI实现将图片上传到本地的示例
2018/09/04 Javascript
在Vue环境下利用worker运行interval计时器的步骤
2019/08/01 Javascript
解决Vue打包上线之后部分CSS不生效的问题
2019/11/12 Javascript
jquery实现拖拽添加元素功能
2020/12/01 jQuery
Python找出list中最常出现元素的方法
2016/06/14 Python
python strip() 函数和 split() 函数的详解及实例
2017/02/03 Python
基于python3 类的属性、方法、封装、继承实例讲解
2017/09/19 Python
Python3.4学习笔记之类型判断,异常处理,终止程序操作小结
2019/03/01 Python
Python面向对象思想与应用入门教程【类与对象】
2019/04/12 Python
Python实现FM算法解析
2019/06/18 Python
Python如何设置指定窗口为前台活动窗口
2020/08/12 Python
运动会广播稿100字
2014/01/11 职场文书
收银员的岗位职责范本
2014/02/04 职场文书
青年文明号创建承诺
2014/03/31 职场文书
测量员岗位职责
2015/02/14 职场文书
暑期辅导班宣传单
2015/07/14 职场文书
聘任通知书
2015/09/21 职场文书
python利用pandas分析学生期末成绩实例代码
2021/07/09 Python
python代码实现备忘录案例讲解
2021/07/26 Python
国庆节到了,利用JS实现一个生成国庆风头像的小工具 详解实现过程
2021/10/05 Javascript
漫画《尖帽子的魔法工坊》宣布动画化
2022/04/06 日漫
Android RecyclerView实现九宫格效果
2022/06/28 Java/Android