如何在Twisted中设置日志级别?

3

我正在使用与Twisted配合的Autobahn软件包,它可以在每次连接到WebSocket时为我显示调试信息。我尝试将日志级别切换为info,但没有成功:

import logging
logging.basicConfig(level=logging.INFO)

有没有简单的方法切换日志级别?

更新。

这是 twisted_service.py 文件:

from twisted.application import service
from twisted.logger import Logger
import logging
logging.basicConfig(level=logging.INFO)


class WebsocketService(service.Service):
    log = Logger()

    def startService(self):
        service.Service.startService(self)
        self.log.debug('start service')

application = service.Application("ws")

ws_service = WebsocketService()
ws_service.setServiceParent(application)

我使用twistd脚本运行它:twistd -noy twisted_service.py,然后我收到了一条消息:

2018-03-03T10:45:22+0500 [builtin.WebsocketService#debug] 开始服务

logging.basicConfig没有起作用。

这个方法是绝对正确的。它应该改变日志记录级别。你真的应该检查一下autobahn包中的日志记录方式。 - Jay Joshi
我也尝试使用twisted.logger.Logger进行自定义日志记录,但无法通过此方法禁用调试级别。 - kalombo
这个问题如果能提供一些你试图抑制的样本日志消息,将会更有帮助。 - Jean-Paul Calderone
我更新了问题。 - kalombo
4个回答

3
我找到了解决方案:
import sys
from twisted.application import service
from twisted.logger import LogLevelFilterPredicate, LogLevel
from twisted.logger import textFileLogObserver, FilteringLogObserver


class WebsocketService(service.Service):
    log = Logger()

    def startService(self):
        service.Service.startService(self)
        self.log.debug('start service')

application = service.Application("ws")

ws_service = WebsocketService()
ws_service.setServiceParent(application)

info_predicate = LogLevelFilterPredicate(LogLevel.info)
log_observer = FilteringLogObserver(textFileLogObserver(sys.stdout), predicates=info_predicate)

application.setComponent(ILogObserver, log_observer)

2
predicats must be an iterator, so it should be log_observer = FilteringLogObserver(textFileLogObserver(sys.stdout), predicates=[info_predicate]) - Dequn

2

要查找所有记录器及其相应的名称,请执行以下操作:

logging.Logger.manager.loggerDict.keys()

尝试通过获取嘈杂的记录器实例来显式设置它:

import logging

noisyLogger = logging.getLogger("autobahn")  # adjust logger name
# noisyLogger.getEffectiveLevel()  # indicates the current effective level
noisyLogger.setLevel(logging.INFO)

我尝试使用您的代码查找所有记录器,只看到了'pyasn1'记录器,但我没有找到我的自定义记录器(请参见我的更新问题)。据我所知,Twisted有自己的日志记录系统,但我无法理解如何管理它。 - kalombo
我在这个字典中没有看到任何twisted.logger.Logger。 - sherpya

2
我使用了kalombo的答案来解决自己项目中的问题,我将分享这里的精华,因为我在这个主题上找不到太多易于访问的信息,并且我还需要弄清楚一些事情。这个例子允许我们同时记录到stdout和文件,并为每个日志级别选择不同的日志级别。
(感谢https://stackoverflow.com/a/46651223/213445关于记录到多个文件的建议。)
以下是详细说明:
- “logtargets”变量是一个FilteringLogObserver实例的列表。 - 每个FilteringLogObserver包装了一个textFileLogObserver,并施加了一个LogLevelFilterPredicate。我们为stdout和“logfile”分别执行此操作。 - LogLevelFilterPredicate通过其“predicates”参数向FilteringLogObserver传递一个最大的LogLevel。 - FilteringLogObserver的“predicates”参数必须是可迭代的,因此在传递它时,我们将LogLevelFilterPredicate包装在列表中。 - 最后,我们将“logtargets”列表传递给globalLogBeginner.beginLoggingTo()。 - 所有未来的Twisted Logger实例都将指向我们的两个日志目标。 - 我们可以有多个Logger实例,每个程序子系统一个,对于每个实例,我们都给它一个单一的参数,即该子系统的日志行命名空间。
import sys
from twisted.logger import Logger, LogLevel, LogLevelFilterPredicate, \
    textFileLogObserver, FilteringLogObserver, globalLogBeginner

logfile = open("application.log", 'a')
logtargets = []

# Set up the log observer for stdout.
logtargets.append(
    FilteringLogObserver(
        textFileLogObserver(sys.stdout),
        predicates=[LogLevelFilterPredicate(LogLevel.warn)]
    )
)

# Set up the log observer for our log file. "debug" is the highest possible level.
logtargets.append(
    FilteringLogObserver(
        textFileLogObserver(logfile),
        predicates=[LogLevelFilterPredicate(LogLevel.debug)]
    )
)

# Direct the Twisted Logger to log to both of our observers.
globalLogBeginner.beginLoggingTo(logtargets)

# Start a logger with a namespace for a particular subsystem of our application.
log = Logger("mynamespace")

log.warn("Goes to both outputs.") # Outputs will start with [mynamespace#warn]
log.error("Also go to both outputs; error is higher priority than warn.")
log.debug("Only goes to log file.")
log.info("Also only goes to log file; info is lower priority than warn.")

0
在这个示例片段中,我演示了将Twisted日志集成到另一个(自定义)日志系统中的场景(其中我省略了代码)。在这种情况下,其他记录器正在管理file对象、stdout/err重定向、文件旋转等。我只想让Twisted 补充那个系统并有效地发送它的消息。
我还展示了如何在Twisted中使用日志级别过滤,以及如何根据需要正确启动和停止它们的记录器。
正如其他答案所示,您需要创建一个绑定到日志文件对象的新“Observer”,并使用“Filter”限制日志记录级别。如果您想要启动/停止/重新启动-请注意,一旦Twisted日志已经被“启动”,就需要将输出重定向到一个新文件(通过一个新的观察者),而不是再次“启动”他们的日志记录。这可以防止警告出现在日志中,如果您尝试多次“启动”Twisted日志。
我还指出,如果已经删除(或从未添加)观察者,则调用theLogPublisher.removeObserver是无害的。因此,在停止后保留观察者引用实际上是为了简单的逻辑流程,尽管可能希望将其设置为None - 即使在某些情况下这可能相当于微小的内存“浪费”。
from twisted.python import log as twistedlog
from twisted.logger import( FilteringLogObserver, textFileLogObserver,
                            LogLevelFilterPredicate, LogLevel )

twistedLogObserver = None

def startTwistedLogging( logFile, level, isStdMsgHdlr=False ):
    global twistedLogObserver
    observer = FilteringLogObserver( textFileLogObserver( logFile ),
                    predicates=[ LogLevelFilterPredicate( level ) ] )
    if twistedLogObserver:
        twistedlog.theLogPublisher.addObserver( observer )
    else: 
        twistedlog.startLoggingWithObserver( observer, setStdout=isStdMsgHdlr )
    twistedLogObserver = observer

def stopTwistedLogging():
    if twistedLogObserver:
        twistedlog.theLogPublisher.removeObserver( twistedLogObserver )

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