无法创建每对象记录器

时间:2017-08-04 19:45:02

标签: python logging

我在Python程序中基于每个模块进行日志记录设置。但是,我还想在子模块中添加每个对象的日志记录,这样自定义类的每个实例都有自己的记录器,它会记录到文件中。

我已经设置了我的应用程序:

app.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
'''
Demo logging app
'''
import os
import log # the app's logging submodule
# path to the current script's dir
scriptdir = os.path.dirname(os.path.realpath(__file__))

def logpath():
    '''
    Return the path to the main log file; needed by the logging.yml
    use this for dynamic output log file paths & names
    '''
    global scriptdir
    # set a timestamped log file for debug log
    scriptname = os.path.basename(__file__)
    script_timestamp = log.timestamp()
    log_file = os.path.join(scriptdir, 'logs', '{0}.{1}.log'.format(scriptname, script_timestamp))
    return(log.logpath(logfile = log_file))

config_yaml = os.path.join(scriptdir, 'logging.yml')
logger = log.log_setup(config_yaml = config_yaml, logger_name = "app")

logger.debug("The app is starting...")
logger.debug("Path to the app's log file: {0}".format(log.logger_filepath(logger = logger, handler_name = "main")))

import submodule

log.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
'''
Functions to set up the program logger
'''

import yaml
import logging
import logging.config
import os

def timestamp():
    '''
    Return a timestamp string
    '''
    import datetime
    return('{:%Y-%m-%d-%H-%M-%S}'.format(datetime.datetime.now()))

def logpath(logfile = 'log.txt'):
    '''
    Return the path to the main log file; needed by the logging.yml
    use this for dynamic output log file paths & names
    '''
    return(logging.FileHandler(logfile))

def log_setup(config_yaml, logger_name):
    '''
    Set up the logger for the script
    config = path to YAML config file
    '''
    # Config file relative to this file
    loggingConf = open(config_yaml, 'r')
    logging.config.dictConfig(yaml.load(loggingConf))
    loggingConf.close()
    return(logging.getLogger(logger_name))

def logger_filepath(logger, handler_name):
    '''
    Get the path to the filehander log file
    '''
    log_file = None
    for h in logger.__dict__['handlers']:
        if h.__class__.__name__ == 'FileHandler':
            logname = h.get_name()
            if handler_name == logname:
                log_file = h.baseFilename
    return(log_file)

submodule.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
'''
Demo logging app submodule
'''
import log
import logging
logger = logging.getLogger("submodule")

logger.debug("loading submodule..")
logger.debug("Path to the submodule's log file: {0}".format(log.logger_filepath(logger = logger, handler_name = "main")))


class MyClass(object):
    '''
    Basic demo class
    '''
    def __init__(self, id):
        self.id = str(id)
        # using the global logger
        logger.debug("Creating MyClass object with id {0}".format(self.id))
        # creating an object specific logger
        self.logger = logging.getLogger(self.id).setLevel(logging.DEBUG)
        self.logger.debug("Started logging for {0}".format(self.id))

x = MyClass(id = "foo")

logging.yml

version: 1
formatters:
  default:
    format: '%(asctime)s:%(name)s:%(module)s:%(funcName)s:%(lineno)d:%(levelname)s:%(message)s'
  console:
    format: '[%(asctime)s] (%(name)s:%(funcName)s:%(lineno)d:%(levelname)s) %(message)s'
    datefmt: "%Y-%m-%d %H:%M:%S"

handlers:
  console:
    class: logging.StreamHandler
    level: DEBUG
    formatter: console
    stream: ext://sys.stdout
  main:
    () : __main__.logpath
    level: DEBUG
    formatter: default

loggers:
  app:
    level: DEBUG
    handlers: [console, main]
    propagate: true
  submodule:
    level: DEBUG
    handlers: [console, main]
    propagate: true

当我尝试运行该应用时,一切正常,直到我尝试在logger中的自定义MyClass对象内创建submodule对象:

$ ./app.py
[2017-08-04 15:41:16] (app:<module>:26:DEBUG) The app is starting...
[2017-08-04 15:41:16] (app:<module>:27:DEBUG) Path to the app's log file: /Users/steve/projects/logging-demo/logs/app.py.2017-08-04-15-41-16.log
[2017-08-04 15:41:16] (submodule:<module>:10:DEBUG) loading submodule..
[2017-08-04 15:41:16] (submodule:<module>:11:DEBUG) Path to the submodule's log file: /Users/steve/projects/logging-demo/logs/app.py.2017-08-04-15-41-16.log
[2017-08-04 15:41:16] (submodule:__init__:21:DEBUG) Creating MyClass object with id foo
Traceback (most recent call last):
  File "./app.py", line 29, in <module>
    import submodule
  File "/Users/steve/projects/logging-demo/submodule.py", line 26, in <module>
    x = MyClass(id = "foo")
  File "/Users/steve/projects/logging-demo/submodule.py", line 24, in __init__
    self.logger.debug("Started logging for {0}".format(self.id))
AttributeError: 'NoneType' object has no attribute 'debug'

有关如何使其发挥作用的任何想法?沿着同一条线,似乎使用此方法并尝试使用logger = logging.getLogger(name)创建任何记录器,其中name未在logging.yml中预先定义YAML文件也有类似的问题。

到目前为止在Python 2.7上测试了这个

1 个答案:

答案 0 :(得分:1)

它在你的代码中:

  

logging.getLogger(self.id).setLevel(logging.DEBUG)

setLevel方法不返回任何内容,因此你的赋值失败并返回“无”。

此代码应该更好用:

self.logger = logging.getLogger(self.id)
self.logger.setLevel(logging.DEBUG)
self.logger.debug("Started logging for {0}".format(self.id))