2017-06-13 46 views
1

通常在C程序(和使用GCC)中,我将创建一个调试打印宏,其中包含当前函数的名称。也就是说,这样的:在Python中打印时包含当前方法名称

#define DPRINTF(fmt, ...) printf("[%s] " fmt, __FUNCTION__, ##__VA_ARGS__) 

使用时,当前的功能将被预置到每个打印,提供在运行时更加有用的调试信息。例如,下面的代码

#include <stdio.h> 

#define DPRINT(fmt, ...) printf("[%s] " fmt, __FUNCTION__, ##__VA_ARGS__) 

void testfunction1(){ 
    DPRINT("Running %d\n",1); 
} 

void testfunction2(){ 
    DPRINT("Running %d\n",2); 
} 

int main(void) { 
    DPRINT("Running: %d\n",0); 
    testfunction1(); 
    testfunction2(); 
    return 0; 
} 

将输出:

[main] Running: 0 
[testfunction1] Running 1 
[testfunction2] Running 2 

能像这样在Python做呢?

我搜索了一下,发现this StackOverflow问题,解释如何使用inspect从堆栈中读取名称。但是,从我发现的Python不支持宏,所以不能使用与我的C程序相同的窗体。

是否有某种机制可以支持这种类型的调试打印?我尝试了lambda表达式,但本例中的“函数名称”打印为“< lambda>”。

+0

它仍然不清楚什么你期待 –

+0

@AmeyYadav ,更新了问题。 – sherrellbc

+0

你可以把你尝试过的示例代码放在哪里,通常很容易从那里开始。为了快速回答,是的,你可以在python中检查装饰器的使用。你可以包装一个函数来调试它的名字。 – suvy

回答

1
import inspect 
import sys 
def DPRINT(fmt, *args): 
    print "{} {} {}".format(sys._getframe(1).f_code.co_name, fmt, args) 

    # below line is another way to get the name of a calling function 
    # print "{} {} {}".format(inspect.stack()[1][3], fmt, args) 

def testfunction1(): 
    DPRINT("Running: 1") 

def testfunction2(): 
    DPRINT("Running: 2") 

def main(): 
    DPRINT("Running: 0") 
    testfunction1() 
    testfunction2() 

main() 

我不知道这可能是有益的

+0

哦..男人。当我正在阅读你的解决方案时,它非常明显。如果您可以从堆栈中读取当前函数的名称,那么您也可以从堆栈中读取调用者的名字。 – sherrellbc

+0

确实如此@sherrellbc –

+1

@AmeyYadav - 读取整个堆栈以抓取最后一帧非常浪费,tho。 – zwer

3

您可以检查的最后一帧检索呼叫者姓名和剩下的就是简单的格式,像

import sys 

def dprint(fmt=None, *args, **kwargs): 
    try: 
     name = sys._getframe(1).f_code.co_name 
    except (IndexError, TypeError, AttributeError): # something went wrong 
     name = "<unknown>" 
    print("[{}] {}".format(name, (fmt or "{}").format(*args, **kwargs))) 

def testfunction1(): 
    dprint("Running {}", 1) 

def testfunction2(): 
    dprint("Running {}", 2) 

def main(): 
    dprint("Running {}", 0) 
    testfunction1() 
    testfunction2() 
    return 0 

if __name__ == "__main__": 
    main() 

# prints: 
# [main] Running 0 
# [testfunction1] Running 1 
# [testfunction2] Running 2 
2

我会建议根本不使用print,而是建立一个logger。记录模块具有适用于所有LogRecordfuncName属性。

你再有(从zwer的回答采取代码):

import logging 

def create_logger(app_name=None): 
    logger = logging.getLogger(app_name or __name__) 
    logger.setLevel(logging.DEBUG) 
    log_format = '[%(asctime)-15s] [%(levelname)08s] (%(funcName)s %(message)s' 
    logging.basicConfig(format=log_format) 
    return logger 

LOGGER = create_logger() 

def testfunction1(): 
    LOGGER.info("Running %d", 1) 

def testfunction2(): 
    LOGGER.error("Running %s", 2) 

def main(): 
    LOGGER.debug("Running %03d", 0) 
    testfunction1() 
    testfunction2() 

if __name__ == "__main__": 
    main() 

这将产生类似于:

[2017-06-13 19:41:45,677] [ DEBUG] (main) Running 000 
[2017-06-13 19:41:45,677] [ INFO] (testfunction1) Running 1 
[2017-06-13 19:41:45,677] [ ERROR] (testfunction2) Running 2 
+0

更健壮的答案 –