您的位置:首页 > 编程语言 > Python开发

python中使用sys模板和logging模块获取行号和函数名的方法

2014-12-25 14:26 1396 查看
From: http://www.jb51.net/article/49026.htm

 

这篇文章主要介绍了python中使用sys模板和logging模块获取行号和函数名的方法,需要的朋友可以参考下

对于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获取Linux下文件版本信息、公司名和产品名的方法
python获取文件版本信息、公司名和产品名的方法
python实现批量获取指定文件夹下的所有文件的厂商信息
Python获取电脑硬件信息及状态的实现方法
使用python编写脚本获取手机当前应用apk的信息
使用 Python 获取 Linux 系统信息的代码
使用Python获取Linux系统的各种信息
python中使用urllib2获取http请求状态码的代码例子
Python 获取新浪微博的最新公共微博实例分享
python通过scapy获取局域网所有主机mac地址示例
python使用ctypes模块调用windowsapi获取系统版本示例
使用Python获取CPU、内存和硬盘等windowns系统信息的2个例子
Python获取文件ssdeep值的方法

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: