【问题标题】:Where does stuff "print" to when not running application from terminal?当不从终端运行应用程序时,东西“打印”到哪里?
【发布时间】:2013-07-09 16:13:47
【问题描述】:

所以我有一个使用 py2app 捆绑到 .app 中的 python 应用程序。我有一些调试打印语句,如果我在终端中运行代码,通常会打印到标准输出。如果我只是打开捆绑的 .app,显然我看不到任何输出。即使我没有看到,这些内容是否真的被打印在某个地方?

【问题讨论】:

  • 您可能应该使用 python 的 logging 模块开始,但是您是否尝试过在 Console.app 中查找?
  • 是的,我认为它可能在那里,但我没有在那里看到它。日志模块是否让它显示在 console.app 中?

标签: python macos stdout py2app


【解决方案1】:

stdout 和 stderr 流重定向到的位置取决于您运行应用程序的方式以及您所在的 OSX 版本。

当您从终端(“MyApp.app/Contents/MacOS/MyApp”)运行应用程序时,输出最终会出现在终端窗口中。

当您通过双击或使用 open(1) 命令运行应用程序时,在使用 10.8 之前的 OSX 时,输出最终会出现在 Console.app 中,而在 OSX 10.8 上会被丢弃。

我有一个补丁可以将输出重定向到 Console.app 甚至对于 OSX 10.8 读取的日志,但目前还没有发布版本。

附:我是py2app的维护者。

【讨论】:

    【解决方案2】:

    它进入标准输出(如果你在命令行中打开它,那么在命令行中,或者如果你使用 cron 作业运行它,则进入日志)。

    如需更高级和更灵活的用法,请尝试使用内置的日志记录支持 (logging module)。它允许您将消息定向到控制台、文件、流(如外部日志服务器)、syslog 进程、电子邮件等,以及基于日志消息级别的过滤器。调试语句(日志语句)仍然可以放置在生产代码中,但配置为不会导致除错误之外的任何日志记录。非常有用,并且大大简化了日志记录。

    【讨论】:

    • 很好,这似乎是我需要的更多。是否可以使用日志记录模块将内容打印到标准输出以及日志,这样如果我在终端中运行某些内容,我只会在终端中看到输出?
    • @vik:是的,任何记录器都可以有多个处理程序。此外,您可以创建非常复杂的日志记录结构(分层记录器,每个都带有或不带有传播,不同的处理程序、过滤器和格式化程序)。 Python 日志记录实际上是一种解决方案,它成为其他一些更新的解决方案(例如 Symfony 的 Monolog)的基础。
    【解决方案3】:

    我想你可能想看看名为 logging 的模块

    您可以使用此模块将自己的日志写入单独的文件,例如,我就是这样做的:

    import logging
    
    # Create a log file for the future debug
    LOG_FILE_NAME = 'my-script.log'
    log_path = path = os.path.join(os.path.expanduser('~'), '/mnt/logs/') 
    if not os.path.exists(log_path):
        os.makedirs(log_path)
    logger = logging.getLogger('my-script')
    logger.setLevel(logging.DEBUG)
    file_handler = logging.FileHandler(log_path+LOG_FILE_NAME)
    file_handler.setLevel(logging.DEBUG)
    file_formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s -%(message)s')
    file_handler.setFormatter(file_formatter)
    logger.addHandler(file_handler)
    
    class Foo()
    
        def log(self, msg, level=None):
            print "LOG %s" % msg
            if level is not None:
                if level == 'INFO':
                    logger.info(msg)
                elif level == 'WARNING':
                    logger.warn(msg)
                elif level == 'ERROR':
                    logger.error(msg)
                elif level == 'CRITICAL':
                    logger.critical(msg)
            else:
                logger.debug(msg) # DEBUG
    
        self.log('Some text here', 'DEBUG') # I use self.log instead of print
    

    【讨论】:

    • 两件事:1) 为什么你坚持要覆盖标准的日志记录行为?看起来这种方法没有给你任何优势? 2)这种方法可以覆盖任何日志记录配置,而更好的方法是只提供标准处理程序(null/no-op 处理程序)并在其他地方处理日志记录配置(例如,看看 Django 的日志记录配置)。跨度>
    • 所以这会将味精打印到标准输出并记录下来?
    • 是的,如果你在终端中运行它会打印出来,并将它们写入日志文件。
    • 您能否更改我的答案以在give standard handler上显示您的意思
    • 我认为应该是log_path = os.path.join(os.path.expanduser('~'), 'mnt/logs/'),因为如果你使用'/mnt/logs/',结果就是这样,因为它有一个前导斜杠。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多