ホームページ >バックエンド開発 >Python チュートリアル >Pythonでsysテンプレートとロギングモジュールを使用して行番号と関数名を取得する方法

Pythonでsysテンプレートとロギングモジュールを使用して行番号と関数名を取得する方法

WBOY
WBOYオリジナル
2016-06-16 08:44:361413ブラウズ

Python については、最近 2 つの問題が私を悩ませています。
1. Python では現在の行番号と関数名を直接取得する方法がありません。これは、誰かがフォーラムで提起した質問で、以下の人々のグループは、Python が __file__ のような __line__ と __func__ を提供しない理由を推測していましたが、最終的には解決策を見つけられませんでした。
2. 関数が自分自身の名前を知らない場合、どうやってそれ自体を再帰的に呼び出すことができますか?これは私の同僚からの質問で、実際には関数名の取得に関するものでしたが、当時は答えることができませんでした。


でも今夜は!すべての質問には答えがあります。
すべては Python のログ モジュールを使用することから始まります。ログの形式には次のオプションがあります。

コードをコピー コードは次のとおりです:

%(name)s ロガー (ロギング チャネル) の名前
%( levelno)s メッセージの数値ログ レベル (DEBUG、INFO、
WARNING、ERROR、CRITICAL)
%(levelname)s メッセージのテキスト ログ レベル ("DEBUG"、"INFO"、
" WARNING"、"ERROR"、"CRITICAL")
%(pathname)s ロギング
呼び出しが発行されたソース ファイルのフル パス名 (利用可能な場合)
%(filename)s ファイル名パス名の部分
%(module)s モジュール (ファイル名の名前部分)
%(lineno)d ロギング呼び出しが発行されたソース行番号
(使用可能な場合)
%(funcName)s関数名
%(created)f LogRecord が作成された時刻 (time.time()
戻り値)
%(asctime)s LogRecord が作成されたテキスト時刻
%(msecs) d 作成時間のミリ秒部分
% (relativeCreated)d LogRecord が作成された時間 (ミリ秒単位)、d スレッド ID (利用可能な場合)
%(threadName)sスレッド名 (
%(スレッド名)s )、レコードが発行される
と同じように計算されます



つまり、ロギングは呼び出し元の行番号と関数名を取得できますが、自分自身の行番号と関数名も取得できるのでしょうか。
ソースコードを見てみましょう。主な部分は次のとおりです。


コードをコピー

コードは次のとおりです:

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
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。