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之复习if语句
Oct 02 Python
python通过pil为png图片填充上背景颜色的方法
Mar 17 Python
用Python的Tornado框架结合memcached页面改善博客性能
Apr 24 Python
浅析python中SQLAlchemy排序的一个坑
Feb 24 Python
用Python写王者荣耀刷金币脚本
Dec 21 Python
pandas全表查询定位某个值所在行列的方法
Apr 12 Python
Python 数据可视化pyecharts的使用详解
Jun 26 Python
使用TensorFlow实现简单线性回归模型
Jul 19 Python
解决django同步数据库的时候app models表没有成功创建的问题
Aug 09 Python
Python xlrd/xlwt 创建excel文件及常用操作
Sep 24 Python
python实现PolynomialFeatures多项式的方法
Jan 06 Python
Pandas 稀疏数据结构的实现
Jul 25 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 日漫
一个简单的自动发送邮件系统(二)
2006/10/09 PHP
一组PHP加密解密函数分享
2014/06/05 PHP
php强大的时间转换函数strtotime
2016/02/18 PHP
PHP实现Google plus的好友拖拽分组效果
2016/10/21 PHP
PHP面向对象中new self()与 new static()的区别浅析
2017/08/17 PHP
PHP回调函数概念与用法实例分析
2017/11/03 PHP
PHP连接MySQL数据库并以json格式输出
2018/05/21 PHP
javascript基于HTML5 canvas制作画箭头组件
2014/06/25 Javascript
jQuery插件扩展操作入门示例
2017/01/16 Javascript
jQuery使用EasyUi实现三级联动下拉框效果
2017/03/08 Javascript
javascript计算对象长度的方法
2017/10/25 Javascript
Js面试算法详解
2018/04/08 Javascript
Vue组件之极简的地址选择器的实现
2018/05/31 Javascript
JS 中可以提升幸福度的小技巧(可以识别更多另类写法)
2018/07/28 Javascript
angular4中*ngFor不能对返回来的对象进行循环的解决方法
2018/09/12 Javascript
js canvas实现橡皮擦效果
2018/12/20 Javascript
JS实现移动端点击按钮复制文本内容
2019/07/28 Javascript
Bootstrap告警框(alert)实现弹出效果和短暂显示后上浮消失的示例代码
2020/08/27 Javascript
进一步理解Python中的函数编程
2015/04/13 Python
Python合并字符串的3种方法
2015/05/21 Python
Python的Flask框架中SQLAlchemy使用时的乱码问题解决
2015/11/07 Python
python抓取网站的图片并下载到本地的方法
2018/05/22 Python
Python Tkinter模块实现时钟功能应用示例
2018/07/23 Python
python对列进行平移变换的方法(shift)
2019/01/10 Python
python中scrapy处理项目数据的实例分析
2020/11/22 Python
奥地利顶级内衣丝袜品牌英国站:Wolford英国
2016/08/29 全球购物
波兰在线香水店:Perfumy.pl
2019/08/12 全球购物
泰国排名第一的家居用品中心:HomePro
2020/11/18 全球购物
网络通讯中,端口有什么含义,端口的取值范围
2012/11/23 面试题
党的群众路线教育学习材料
2014/05/12 职场文书
考研英语辞职信
2015/05/13 职场文书
Python 中数组和数字相乘时的注意事项说明
2021/05/10 Python
Python Parser的用法
2021/05/12 Python
python中opencv实现图片文本倾斜校正
2021/06/11 Python
SQL Server远程连接的设置步骤(图文)
2022/03/23 SQL Server