有没有办法使编写Python记录器更像编写打印语句?

时间:2018-08-17 00:50:08

标签: python-3.x debugging

我最近使用python,并且我一直在编写的代码开始变得足够大,以至于我开始切换打印语句,因此我环顾四周,看看SO推荐什么,{{3 }}将every记录为community votes的时间,should use,但是关于如何配置它以使其易于使用的讨论和文档令人困惑,并且instead of print

但是,我发现记录器版本的书写语句更耗时,而且人解析起来也更困难,而且看起来很简单:

let {
  promisify
} = require('util');
let {
  google
} = require('googleapis');
let sheets = google.sheets('v4');
let credentials = require('./credentials.json')

let client = new google.auth.JWT(
  credentials.client_email, null, credentials.private_key, ['https://www.googleapis.com/auth/spreadsheets'])
client.authorize((err, tokens) => {
  if (err) {
    throw err;
  }
});

let endpoint = promisify(sheets.spreadsheets.values.get);

async function test() {

  let request = {
    auth: client,
    spreadsheetId: "xxxxxxxx",
    range: "'ExampleSheet'!A:B",
    valueRenderOption: "UNFORMATTED_VALUE",
    majorDimension: "ROWS",
  }

  let result = await endpoint(request)
    .then((res) => {
      return res
    })
    .catch((err) => {
      console.log(err);
    });
}

test();

vs

print (‘First value is:‘, val1, ‘Second value is‘, val2)

除了使用以下内容滚动我自己的调试级别之外:

logger.info(‘value 1 is: %s , value 2 is: %s’, val1, val2)

我可以做些什么使记录语句更容易阅读吗?还是我应该尝试其他包装?

2 个答案:

答案 0 :(得分:2)

两个选项。

1)stdlib记录时间很长。尝试使用其他库。我喜欢structlog。这是键/值记录:

>>> import structlog
>>> log = structlog.get_logger()
>>> log.info('some event', val1='first value', val2='second value')
2018-08-16 21:01.02 some event                   val1=first value val2=second value

2)实际上,您可以根据需要继续使用打印呼叫。实际上,对于流行的Twelve-Factor App方法,这是推荐的最佳实践,其中日志事件只是stdout上的行。  通常每行都是一个序列化的json对象,但这不是唯一明智的选择。

  

一个由十二个因素组成的应用程序从不关心其输出流的路由或存储。它不应尝试写入或管理日志文件。而是,每个正在运行的进程将其未缓冲的事件流写入stdout。

这里的想法是,在OS级别上已经有功能强大且灵活的日志记录解决方案,我们应该仅仅利用这些解决方案,而不是重新发明轮子。例如,您可以将您的应用通过管道运行到syslog中:

./myapp.py | logger -t myapp &

答案 1 :(得分:1)

如果只是语法糖,类似

def info (logger, *args):
    logger.info("".join(str(item) for item in args))

将使您几乎像print那样写:

info(my_logger, 'First value is:', val1, 'Second value is', val2)

可以通过猴子补丁程序来为您执行此操作,但这可能不是一个好主意-更改stdlib对象的行为会激怒下一个接您的代码的人。如果您希望保持常规记录器的外观,但又不至于因业而生,则可以添加一个简单的shim类来进行组装:

class LogShim (object):

    def __init__(self, logger):
        self.logger = logger

    def log(self, level, *msg):
        if self.logger.isEnabledFor(level):
            concatenated =  " ".join(str(a) for a in msg)
            self.logger.log(level, concatenated)

    def debug(self, *msg):
        self.logger.log(logging.DEBUG, *msg)

    def info(self, *msg):
        self.log(logging.INFO, *msg)

    def warning(self, *msg):
        self.log(logging.WARNING, *msg)

    def error(self, *msg):
        self.log(logging.ERROR, *msg)

    def critical(self, *msg):
        self.log(logging.CRITICAL, *msg)

然后像记录器一样使用它:

my_logger = logging.getLogger()
my_shim = LogShim(my_logger)
my_shim.debug("here", "are", 4, "items")