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中__call__用法实例
Aug 29 Python
python获取外网ip地址的方法总结
Jul 02 Python
python学习之第三方包安装方法(两种方法)
Jul 30 Python
Python解析json文件相关知识学习
Mar 01 Python
Python实现的当前时间多加一天、一小时、一分钟操作示例
May 21 Python
Python实现的生产者、消费者问题完整实例
May 30 Python
Python实现的逻辑回归算法示例【附测试csv文件下载】
Dec 28 Python
pyqt5 comboBox获得下标、文本和事件选中函数的方法
Jun 14 Python
Python 切分数组实例解析
Nov 07 Python
Python实现子类调用父类的初始化实例
Mar 12 Python
Python实现加密接口测试方法步骤详解
Jun 05 Python
python flask框架快速入门
May 14 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实现的下载css文件中的图片的代码
2010/02/08 PHP
php allow_url_include的应用和解释
2010/04/22 PHP
使用PHPMyAdmin修复论坛数据库的图文方法
2012/01/09 PHP
PHP获取栏目的所有子级和孙级栏目的ID号示例
2014/04/01 PHP
PHP+Ajax实现验证码的实时验证
2016/07/20 PHP
Nginx实现反向代理
2017/09/20 Servers
javascript-简单的计算器实现步骤分解(附图)
2013/05/30 Javascript
获取表单控件原始(初始)值的方法
2013/08/21 Javascript
javascript闭包入门示例
2014/04/30 Javascript
解决ueditor jquery javascript 取值问题
2014/12/30 Javascript
浅析node连接数据库(express+mysql)
2015/11/30 Javascript
js+ajax实现获取文件大小的方法
2015/12/08 Javascript
如何处理JSON中的特殊字符
2016/11/30 Javascript
bootstrap日期控件问题(双日期、清空等问题解决)
2017/04/19 Javascript
通过js修改input、select默认字体颜色
2017/04/19 Javascript
JavaScript设计模式之单例模式详解
2017/06/09 Javascript
基于angular-utils-ui-breadcrumbs使用心得(分享)
2017/11/03 Javascript
vue全局组件与局部组件使用方法详解
2018/03/29 Javascript
vue、react等单页面项目部署到服务器的方法及vue和react的区别
2018/09/29 Javascript
Android 自定义view仿微信相机单击拍照长按录视频按钮
2019/07/19 Javascript
Python实现Windows上气泡提醒效果的方法
2015/06/03 Python
django基础之数据库操作方法(详解)
2017/05/24 Python
基于Python函数和变量名解析
2019/07/19 Python
Python实现序列化及csv文件读取
2020/01/19 Python
python下对hsv颜色空间进行量化操作
2020/06/04 Python
css背景图片的背景裁切、背景透明度、背景变换等效果运用
2012/12/24 HTML / CSS
英国皇家造币厂:The Royal Mint
2018/10/05 全球购物
英国女性运动服品牌:Sweaty Betty
2018/11/08 全球购物
自主招生自荐书
2013/11/29 职场文书
招聘与培训专员岗位职责
2014/01/30 职场文书
财务会计自荐信范文
2014/02/21 职场文书
大学新生军训感言
2014/02/25 职场文书
捐书倡议书
2014/08/29 职场文书
2015大学迎新晚会策划书
2015/07/16 职场文书
创作书写之导游词实用技巧分享(干货)
2019/12/20 职场文书
MySQL中order by的使用详情
2021/11/17 MySQL