仅使用打印语句进行调试

问题:仅使用打印语句进行调试

最近我一直在用Python编写很多代码。而且我一直在处理以前从未使用过的数据,使用从未见过的公式来处理大型文件。所有这些使我写了很多打印语句来验证是否一切正常,并确定故障点。但是,通常,输出太多信息不是一个好习惯。仅当我要调试时才使用打印语句,而当我不希望打印它们时如何跳过它们?

I have been coding a lot in Python of late. And I have been working with data that I haven’t worked with before, using formulae never seen before and dealing with huge files. All this made me write a lot of print statements to verify if it’s all going right and identify the points of failure. But, generally, outputting so much information is not a good practice. How do I use the print statements only when I want to debug and let them be skipped when I don’t want them to be printed?


回答 0

logging模块具有您想要的一切。乍一看似乎有些多余,但只使用您需要的零件。我推荐使用logging.basicConfig切换日志级别stderr简单的日志方法debuginfowarningerrorcritical

import logging, sys
logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
logging.debug('A debug message!')
logging.info('We processed %d records', len(processed_records))

The logging module has everything you could want. It may seem excessive at first, but only use the parts you need. I’d recommend using logging.basicConfig to toggle the logging level to stderr and the simple log methods, debug, info, warning, error and critical.

import logging, sys
logging.basicConfig(stream=sys.stderr, level=logging.DEBUG)
logging.debug('A debug message!')
logging.info('We processed %d records', len(processed_records))

回答 1

一种简单的方法是调用日志记录函数:

DEBUG = True

def log(s):
    if DEBUG:
        print s

log("hello world")

然后,可以更改DEBUG有无日志记录的值并运行代码。

标准logging模块对此具有更完善的机制。

A simple way to do this is to call a logging function:

DEBUG = True

def log(s):
    if DEBUG:
        print s

log("hello world")

Then you can change the value of DEBUG and run your code with or without logging.

The standard logging module has a more elaborate mechanism for this.


回答 2

使用日志记录内置库模块代替打印。

创建一个Logger对象(例如logger),然后在此之后,每当插入调试打印时,您只需放置:

logger.debug("Some string")

您可以logger.setLevel在程序开始时使用来设置输出电平。如果将其设置为DEBUG,它将打印所有调试信息。将其设置为INFO或更高,所有调试将立即消失。

您还可以使用它记录不同级别(信息,警告和错误)的更严重的事件。

Use the logging built-in library module instead of printing.

You create a Logger object (say logger), and then after that, whenever you insert a debug print, you just put:

logger.debug("Some string")

You can use logger.setLevel at the start of the program to set the output level. If you set it to DEBUG, it will print all the debugs. Set it to INFO or higher and immediately all of the debugs will disappear.

You can also use it to log more serious things, at different levels (INFO, WARNING and ERROR).


回答 3

首先,我将第二次提名python的日志记录框架。但是,请谨慎使用它。具体来说:让日志记录框架扩展您的变量,而不要自己做。例如,代替:

logging.debug("datastructure: %r" % complex_dict_structure)

确保您这样做:

logging.debug("datastructure: %r", complex_dict_structure)

因为尽管它们看上去很相似,但第一个版本即使已禁用也会产生repr()成本。第二个版本避免这种情况。同样,如果您自己动手,我建议采取以下措施:

def debug_stdout(sfunc):
    print(sfunc())

debug = debug_stdout

通过以下方式调用:

debug(lambda: "datastructure: %r" % complex_dict_structure)

如果您通过执行以下操作将其禁用,这将再次避免开销:

def debug_noop(*args, **kwargs):
    pass

debug = debug_noop

除非它们是1)计算成本高或2)debug语句处于n ^ 3循环之类的中间,否则计算这些字符串的开销可能并不重要。并不是说我对此一无所知。

First off, I will second the nomination of python’s logging framework. Be a little careful about how you use it, however. Specifically: let the logging framework expand your variables, don’t do it yourself. For instance, instead of:

logging.debug("datastructure: %r" % complex_dict_structure)

make sure you do:

logging.debug("datastructure: %r", complex_dict_structure)

because while they look similar, the first version incurs the repr() cost even if it’s disabled. The second version avoid this. Similarly, if you roll your own, I’d suggest something like:

def debug_stdout(sfunc):
    print(sfunc())

debug = debug_stdout

called via:

debug(lambda: "datastructure: %r" % complex_dict_structure)

which will, again, avoid the overhead if you disable it by doing:

def debug_noop(*args, **kwargs):
    pass

debug = debug_noop

The overhead of computing those strings probably doesn’t matter unless they’re either 1) expensive to compute or 2) the debug statement is in the middle of, say, an n^3 loop or something. Not that I would know anything about that.


回答 4

我对其他人一无所知,但是我习惯于定义一个“全局常量”DEBUG),然后定义一个仅在时才debug(msg)打印的全局函数()。msgDEBUG == True

然后,我编写如下的调试语句:

debug('My value: %d' % value)

…然后我进行单元测试,再也没有做过!:)

I don’t know about others, but I was used to define a “global constant” (DEBUG) and then a global function (debug(msg)) that would print msg only if DEBUG == True.

Then I write my debug statements like:

debug('My value: %d' % value)

…then I pick up unit testing and never did this again! :)