博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
python中获取当前位置所在的行号和函数名
阅读量:6551 次
发布时间:2019-06-24

本文共 5141 字,大约阅读时间需要 17 分钟。

  hot3.png

http://www.vimer.cn/2010/12/%E5%9C%A8python%E4%B8%AD%E8%8E%B7%E5%8F%96%E5%BD%93%E5%89%8D%E4%BD%8D%E7%BD%AE%E6%89%80%E5%9C%A8%E7%9A%84%E8%A1%8C%E5%8F%B7%E5%92%8C%E5%87%BD%E6%95%B0%E5%90%8D.html

对于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_backdef 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 rvdef _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)

的三个值分别为文件名,行号,函数名。(可以去来看一下代码中几个系统函数的说明)

OK,如果已经看懂了源码,那获取当前位置的行号和函数名相信也非常清楚了,代码如下:

#!/usr/bin/python# -*- coding: utf-8 -*-'''#=============================================================================#  Author:          dantezhu - http://www.vimer.cn#  Email:           zny2008@gmail.com#  FileName:        xf.py#  Description:     获取当前位置的行号和函数名#  Version:         1.0#  LastChange:      2010-12-17 01:19:19#  History:         #============================================================================='''import sysdef 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 sysdef get_cur_info():    print sys._getframe().f_code.co_name    print sys._getframe().f_back.f_code.co_nameget_cur_info()

 

 

================================================================================

另外,利用python的 inspect 模块中的getframeinfo也可以得到.

inspect.getframeinfo(
frame [,
context ])

Get information about a frame or traceback object. A 5-tuple is returned, the last five elements of the frame’s frame record.

Changed in version 2.6: Returns a named tuple Traceback(filename, lineno, function, code_context, index).

转载于:https://my.oschina.net/qihh/blog/74244

你可能感兴趣的文章
如何修改redhat7.2的ROOT密码
查看>>
mysql面试题
查看>>
Zabbix3.0.12部署
查看>>
腾讯技术工程 | 腾讯AI Lab解析2017 NIPS三大研究方向,启动教授及学生合作项目...
查看>>
Ubuntu版本代号
查看>>
sel4j错误记录
查看>>
搭建android + cordova环境
查看>>
老男孩Linux50期决心书
查看>>
Petya勒索病毒疫苗出现,分分钟让电脑对病毒免疫
查看>>
实现memcmp函数
查看>>
vim编辑器的附加功能
查看>>
centos lvs+keepalived 双机实现互备且同为realserver
查看>>
centos6.5监控平台nagios搭建与配置
查看>>
[C#基础知识系列]全面解析C#中静态与非静态
查看>>
活动目录域及工作组环境外部时间源同步
查看>>
ACS USB安装引导制作
查看>>
我的友情链接
查看>>
如何下载导入以及安装Cisco路由器交换机License
查看>>
lync客户端外网登陆提示exchange连接错误
查看>>
硬盘根目录里的Msdia80.dll文件
查看>>