Python日志在Windows上工作,但在Mac OS上不工作

Python日志在Windows上工作,但在Mac OS上不工作,python,windows,macos,logging,Python,Windows,Macos,Logging,我使用上面的代码创建了一个记录器,我可以在我的模块中使用它将消息打印到屏幕上,同时将消息打印到文本文件中 在Windows上,消息将同时输出到文件和屏幕。然而,在MacOSX10.9.5上,它们只得到文件的输出。我正在使用Python 2.7 关于如何解决这个问题,您有什么想法吗?从您的问题可以清楚地看出,您在创建记录器名称方面没有问题, 日志文件名和日志记录到一个文件,所以我将简化这部分,以保持代码简洁 第一件事:在我看来,您的解决方案似乎是正确的,即日志记录。StreamHandler应该

我使用上面的代码创建了一个
记录器
,我可以在我的模块中使用它将消息打印到屏幕上,同时将消息打印到文本文件中

在Windows上,消息将同时输出到文件和屏幕。然而,在MacOSX10.9.5上,它们只得到文件的输出。我正在使用Python 2.7


关于如何解决这个问题,您有什么想法吗?

从您的问题可以清楚地看出,您在创建记录器名称方面没有问题, 日志文件名和日志记录到一个文件,所以我将简化这部分,以保持代码简洁

第一件事:在我看来,您的解决方案似乎是正确的,即
日志记录。StreamHandler
应该 默认情况下,将输出发送到
sys.stderr
。您可能有一些代码(而不是 显示在您的问题中),它正在修改sys.stderr,或者您正在运行 您在OSX上的代码以这样一种方式显示,即不会显示到stderr的输出(而是 实际输出)

带有
日志记录的解决方案
使用_logging.py将以下代码放入

# Logging
cur_flname = os.path.splitext(os.path.basename(__file__))[0]
LOG_FILENAME = constants.log_dir + os.sep + 'Log_' + cur_flname + '.txt'
util.make_dir_if_missing(constants.log_dir)
logging.basicConfig(filename=LOG_FILENAME, level=logging.INFO, filemode='w',
                    format='%(asctime)s %(levelname)s %(module)s - %(funcName)s: %(message)s',
                    datefmt="%m-%d %H:%M")  # Logging levels are DEBUG, INFO, WARNING, ERROR, and CRITICAL
# Output to screen
logger = logging.getLogger(cur_flname)
logger.addHandler(logging.StreamHandler())
from logbook import Logger

log = Logger(__name__)

log.info("information")
log.warning("warning")


def fun():
    log.info(" fun inf")
    log.warning("fun warn")
运行它:
$python with_logging.py
,您将看到预期的日志记录(格式正确) 在日志文件
app.log
stderr

注意,如果您在
stderr
上看不到它,则有东西隐藏了您的stderr 输出。要查看某些内容,请在
StreamHandler
中将流更改为
sys.stdout

带有
日志的解决方案
logbook
是python包提供的替代日志记录方法。我在这里展示它是为了展示主要功能 与stdlib
logging
:使用
logbook
对我来说,使用和配置似乎更简单

上一个解决方案使用_logbook.py重写为

主要区别在于,您不必将处理程序附加到记录器,记录器只需发出
一些日志记录

这些记录如果放在适当的位置,将由处理程序处理。一种方法 是创建一个处理程序并在其上调用
push\u application()
。这将使 将处理程序放入正在使用的处理程序堆栈中

和前面一样,我们需要两个处理程序,一个用于文件,另一个用于stderr

如果使用_logbook.py运行此脚本
$python
,您将看到与 使用日志记录

将日志设置与模块代码分开:
short\u logbook.py
使用stdlib
logging
I确实不喜欢让logger工作的介绍性舞蹈。我想要 只需发出一些日志记录,并希望尽可能简单地这样做

以下示例是对前一个示例的修改。而不是建立 在模块的最开始登录时,我会在代码运行之前进行登录 -在
中,如果uuuu name uuuu==“uuuuu main”
(您可以在任何其他 地点)

出于实际原因,我将模块和调用代码分离为两个文件:

文件
funmodule.py

import logbook
import sys

logformat = ("{record.time:%m-%d %H:%M} {record.level_name} {record.module} - "
             "{record.func_name}: {record.message}")
kwargs = {"level": logbook.INFO, "format_string": logformat, "bubble": True}

logbook.StreamHandler(sys.stderr, **kwargs).push_application()
logbook.FileHandler("app.log", **kwargs).push_application()

logger = logbook.Logger("app")

logger.info("information")
logger.warning("warning")


def fun():
    logger.info(" fun inf")
    logger.warning("fun warn")

if __name__ == "__main__":
    fun()
您可以注意到,实际上只有两行代码与制作相关 日志记录可用

然后,创建调用代码,放入
short\u logbook.py

# Logging
cur_flname = os.path.splitext(os.path.basename(__file__))[0]
LOG_FILENAME = constants.log_dir + os.sep + 'Log_' + cur_flname + '.txt'
util.make_dir_if_missing(constants.log_dir)
logging.basicConfig(filename=LOG_FILENAME, level=logging.INFO, filemode='w',
                    format='%(asctime)s %(levelname)s %(module)s - %(funcName)s: %(message)s',
                    datefmt="%m-%d %H:%M")  # Logging levels are DEBUG, INFO, WARNING, ERROR, and CRITICAL
# Output to screen
logger = logging.getLogger(cur_flname)
logger.addHandler(logging.StreamHandler())
from logbook import Logger

log = Logger(__name__)

log.info("information")
log.warning("warning")


def fun():
    log.info(" fun inf")
    log.warning("fun warn")
运行代码时,您将看到它的工作方式与以前相同,只有记录器名称为
funmodule

请注意,我在设置日志记录后从funmodule import fun执行了
。如果我在网上做的话
顶部如果
short_logbook.py
文件,则不会看到
funmodule.py
中的前两条日志记录 因为它们发生在模块导入期间

编辑:添加另一个
日志记录
解决方案以进行公平比较

又一个stdlib
日志记录
解决方案 试图对
日志
日志
进行公平比较,我将最后的
日志
示例改写为
日志记录

funmodule\u logging.py
看起来像:

import sys
import logbook

if __name__ == "__main__":
    logformat = ("{record.time:%m-%d %H:%M} {record.level_name} {record.module}"
                 "- {record.func_name}: {record.message}")
    kwargs = {"level": logbook.INFO, "format_string": logformat, "bubble": True}

    logbook.StreamHandler(sys.stderr, **kwargs).push_application()
    logbook.FileHandler("app.log", **kwargs).push_application()

    from funmodule import fun
    fun()
short_logging.py
如下所示:

import logging

log = logging.getLogger(__name__)

log.info("information")
log.warning("warning")


def fun():
    log.info(" fun inf")
    log.warning("fun warn")
    log.error("no fun at all")
功能非常相似

我仍然为伐木而挣扎。stdlib
logging
不容易掌握,但它在stdlib中提供了 一些不错的功能,比如
logging.config.dictConfig
允许通过字典配置日志记录。
logbook
一开始就简单得多,但目前速度有点慢,缺少
dictConfig。无论如何,这些差异与您的问题无关。

您能否显示其他变量,尤其是
常量
?看起来像是常量。log\u dir
包含反斜杠```因此在Mac上被误解。谢谢@EugeneLisitsky,
常量。log\u dir
看起来像这样:
'/Users/ri/Documents/Projects//GL/Output//GL Logs'
确定。我试过你的代码,它记录得很好,除了屏幕日志没有日期严重性和其他信息。您能检查一下sys.stdout或sys.stderr上面的某个地方是否被重定向到/dev/null或其他地方吗?“我不知道为什么,但这里有我编写的一些新代码的3个版本,它们似乎可以工作”,这是一个非常糟糕的答案IMO@xavier您可能误解了我的最后一个注释-这是关于我对
日志记录的感受,不是承认我的代码有效,但我不知道为什么。以上所有示例都是工作示例(安装
logbook
软件包,然后您可以尝试所有示例),如果您需要,我可以向您解释任何行。但请先阅读并测试一下,然后再发送下一个反应。这不是我的意思。问题是关于“为什么我的代码不能在OSX上工作”。您的回答是“我不知道为什么,可能是其他代码导致了问题。”这应该作为一个注释,而不是偏离日志与日志的界限。@xavier我明白了。你是对的,我没有发现它在OSX上不起作用的确切原因。很难强迫作者提供完整的运行示例。我的猜测是,问题的真正根源在于难以以简单的方式使用
日志记录
库-这通常会导致混乱的代码,而没有人可以访问