Python打印信息最佳切换方式是什么?

10
我在一个游戏引擎中运行Python 2.4,我想在需要时关闭所有的打印输出。例如,我希望在调试构建中启用打印,然后在发布构建中关闭打印。并且它必须尽可能地透明。
在引擎的C代码中,我的解决方案是将printf函数放置在vararg宏内,并在发布构建中将其定义为什么都不做。
这是我的当前解决方案:
DebugPrints = True
def PRINT (*args):
    global DebugPrints
    if DebugPrints:
        string = ""
        for arg in args:
            string += " " + str(arg)
        print string

它可以轻松切换打印输出,但是可能有更好的方法来格式化字符串。我的主要问题是这实际上向程序添加了更多的函数调用。

我想知道是否有任何方法可以修改打印关键字的工作方式?


你可以使用 print " ".join(args) 代替 for 循环。 - Daren Thomas
哎呀,应该是print " ".join(map(str, args))。 - Daren Thomas
6个回答

13

是的,你可以将 sys.stdout 分配给任何你想要的东西。创建一个有一个不执行任何操作的 write 方法的小类:

class DevNull(object):
    def write(self, arg):
        pass

import sys    
sys.stdout = DevNull()
print "this goes to nirvana!"

通过同样的技巧,您也可以将打印内容记录到文件中,只需将 sys.stdout 设置为已打开的文件对象即可。


不要忘记备份 sys.stdout,如果您希望稍后重新启用它。_stdout = sys.stdout; sys.stdout = DevNull() - Christian Witts
有了像“logging”这样的模块,这种方法似乎有点荒谬。 - Jeremy Cantrell
“Ridiculous”有点过头了,但我明白你的意思。也许我应该把问题命名为“最简单的切换打印方式”? - Nathan Ross Powell

11

我知道已经有一个被标记为正确的答案了,但是Python有一个debug标志可以提供更清晰的解决方案。你可以像这样使用它:

if __debug__:
    print "whoa"
如果你使用 -O 或 -OO(通常用于发布构建)来调用 Python,__debug__ 将被设置为 False。更好的是,__debug__ 是解释器的一个特殊情况;当它写入 pyc/pyo 文件时,它会真正删除那些代码,使得最终代码更小/更快。请注意,你不能给 __debug__ 赋值,因此它完全基于那些命令行参数。

+1:这是有用的知识,即使实现起来需要更多的努力。 - Nathan Ross Powell
当你只是使用python ./thescript.py(而不是使用-d调试标志)时,调试标志开启有点可惜。 - dbr

9

日志记录模块(logging module)是“最佳”的方式,尽管我经常使用一些简单的方法,比如..

class MyLogger:
    def _displayMessage(self, message, level = None):
        # This can be modified easily
        if level is not None:
            print "[%s] %s" % (level, message
        else:
            print "[default] %s" % (message)

    def debug(self, message):
        self._displayMessage(message, level = "debug")
    def info(self, message):
        self._displayMessage(message, level = "info")

log = MyLogger()
log.info("test")

3
不要使用print,而是创建一个控制台类来处理所有的打印。只需调用控制台,控制台可以决定是否实际打印它们。控制台类也适用于错误和警告消息或重定向输出的情况。

是的,值得一看的是现有的日志记录模块。根据项目的范围,一个小类可能就足够了。 - Matthew Olenik

1
如果您真的想切换打印:

>>> import sys
>>> import os
>>> print 'foo'
foo
>>> origstdout = sys.stdout
>>> sys.stdout = open(os.devnull, 'w')
>>> print 'foo'
>>> sys.stdout = origstdout
>>> print 'foo'
foo

然而,我建议你只在临时代码中使用print。对于像原问题描述的真正的应用程序,请使用logging。它允许滑动比例的冗长程度,因此你可以只记录重要的日志信息,或者记录通常不太重要的细节的更冗长的日志信息。
>>> import logging
>>> logging.basicConfig(level=logging.DEBUG)
>>> logging.debug('foo')
DEBUG:root:foo

例如,使用可能是在代码中添加调试日志。然后要将其静音,请将级别更改为更高的级别之一:INFOWARNWARNINGERRORCRITICALFATAL
>>> logging.root.setLevel(logging.INFO)
>>> logging.debug('foo')
>>>

在脚本中,你只需像这样在basicConfig中设置它:
import logging
logging.basicConfig(level=logging.INFO)

logging.debug('foo') # this will be silent

更复杂的日志记录用法可以在文档中找到。

0

我在另一篇帖子中回答了这个问题,但是该问题被标记为重复:

无论如何,这是我会做的:

from __future__ import print_function
DebugPrints = 0

def print(*args, **kwargs):
    if DebugPrints:
        return __builtins__.print(*args, **kwargs)

print('foo') # doesn't get printed
DebugPrints = 1
print('bar') # gets printed

遗憾的是,您无法保留py2的打印语法:print 'foo'


运行得很好。但是如果enable_print不是全局的,也没有作为参数传递,那么打印函数怎么知道它呢? - Pyderman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接