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 递归遍历文件夹,并打印满足条件的文件路径实例
Aug 30 Python
快速了解python leveldb
Jan 18 Python
python利用requests库进行接口测试的方法详解
Jul 06 Python
Python中垃圾回收和del语句详解
Nov 15 Python
使用python将图片按标签分入不同文件夹的方法
Dec 08 Python
用Python PIL实现几个简单的图片特效
Jan 18 Python
详解Python 字符串相似性的几种度量方法
Aug 29 Python
python计算导数并绘图的实例
Feb 29 Python
Python利用PyPDF2库获取PDF文件总页码实例
Apr 03 Python
Python中操作各种多媒体,视频、音频到图片的代码详解
Jun 04 Python
python3实现将json对象存入Redis以及数据的导入导出
Jul 16 Python
python和opencv构建运动检测器的实现
Mar 03 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 中执行系统外部命令
2006/10/09 PHP
PHP 函数call_user_func和call_user_func_array用法详解
2014/03/02 PHP
Yii框架表单提交验证功能分析
2017/01/07 PHP
IE Firefox 使用自定义标签的区别
2009/10/15 Javascript
jQuery 1.4 15个你应该知道的新特性(译)
2010/01/24 Javascript
js跑步算法的实现代码
2013/12/04 Javascript
jquery如何扑捉回车键触发的事件
2014/04/24 Javascript
jQuery中的$.ajax()方法应用
2014/05/06 Javascript
实例讲解避免javascript冲突的方法
2016/01/03 Javascript
Node.js 应用跑得更快 10 个技巧
2016/04/03 Javascript
jQuery实现选项联动轮播效果【附实例】
2016/04/19 Javascript
jQuery如何防止Ajax重复提交
2016/10/14 Javascript
JS中关于事件处理函数名后面是否带括号的问题
2016/11/16 Javascript
在JS中如何把毫秒转换成规定的日期时间格式实例
2017/05/11 Javascript
EasyUI在Panel上动态添加LinkButton按钮
2017/08/11 Javascript
JQuery+Bootstrap 自定义全屏Loading插件的示例demo
2019/07/03 jQuery
vue.js实现简单购物车功能
2020/05/30 Javascript
MySQL中表的复制以及大型数据表的备份教程
2015/11/25 Python
Python使用ConfigParser模块操作配置文件的方法
2018/06/29 Python
python实现汽车管理系统
2018/11/30 Python
详解opencv Python特征检测及K-最近邻匹配
2019/01/21 Python
详解django中url路由配置及渲染方式
2019/02/25 Python
PyQt4 treewidget 选择改变颜色,并设置可编辑的方法
2019/06/17 Python
使用python爬取微博数据打造一颗“心”
2019/06/28 Python
Python Pandas数据分析工具用法实例
2020/11/05 Python
韩国三星集团旗下时尚品牌官网:SSF SHOP
2016/08/02 全球购物
德国游戏机商店:Konsolenkost
2019/12/08 全球购物
static全局变量与普通的全局变量有什么区别?static局部变量和普通局部变量有什么区别?static函数与普通函数有什么区别?
2015/02/22 面试题
数据库基础的一些面试题
2012/02/25 面试题
上海某公司.net方向笔试题
2014/09/14 面试题
大学生创业策划书
2014/02/02 职场文书
大学竞选班干部演讲稿
2014/08/21 职场文书
超市啤酒狂欢夜策划方案范文!
2019/07/03 职场文书
MySQL系列之三 基础篇
2021/07/02 MySQL
利用 Python 的 Pandas和 NumPy 库来清理数据
2022/04/13 Python
Debian11 Xfce终端光标的颜色怎么设置?
2022/08/14 数码科技