【Free Style】华为云之Python实践(三)

举报
yd_79585289 发表于 2017/11/24 07:48:07 2017/11/24
【摘要】 使用 __name__ 作为 logger 的名称虽然不是非得将 logger 的名称设置为 __name__ ,但是这样做会给我们带来诸多益处。在 python 中,变量 __name__ 的名称就是当前模块的名称。比如,在模块 “foo.bar.my_module” 中调用 logger.getLogger(__name__) 等价于调用logger.getLogger(“foo.bar.my

使用 __name__ 作为 logger 的名称

虽然不是非得将 logger 的名称设置为 __name__ ,但是这样做会给我们带来诸多益处。在 python 中,变量 __name__ 的名称就是当前模块的名称。比如,在模块 “foo.bar.my_module” 中调用 logger.getLogger(__name__) 等价于调用logger.getLogger(“foo.bar.my_module”) 。当你需要配置 logger 时,你可以配置到 “foo” 中,这样包 foo 中的所有模块都会使用相同的配置。当你在读日志文件的时候,你就能够明白消息到底来自于哪一个模块。

捕捉异常并使用 traceback 记录它

出问题的时候记录下来是个好习惯,但是如果没有 traceback ,那么它一点儿用也没有。你应该捕获异常并用 traceback 把它们记录下来。比如下面这个例子:

Python

1

2

3

4

5

6

try:

    open('/path/to/does/not/exist', 'rb')

except (SystemExit, KeyboardInterrupt):

    raise

except Exception, e:

    logger.error('Failed to open file', exc_info=True)

使用参数 exc_info=true 调用 logger 方法, traceback 会输出到 logger 中。你可以看到下面的结果:

Python

1

2

3

4

5

ERROR:__main__:Failed to open file

Traceback (most recent call last):

  File "example.py", line 6, in <module>

    open('/path/to/does/not/exist', 'rb')

IOError: [Errno 2] No such file or directory: '/path/to/does/not/exist'

你也可以调用 logger.exception(msg, _args),它等价于 logger.error(msg, exc_info=True, _args)。

千万不要在模块层次获取 Logger,除非 disable_existing_loggers 被设置为 False

你可以看到很多在模块层次获取 logger 的例子(在这篇文章我也使用了很多,但这仅仅为了让示例更短一些)。它们看上去没什么坏处,但事实上,这儿是有陷阱的 – 如果你像这样在模块中使用 Logger,Python 会保留从文件中读入配置前所有创建的所有 logger。

my_module.py

Python

1

2

3

4

5

6

7

8

9

10

import logging

 

logger = logging.getLogger(__name__)

 

def foo():

    logger.info('Hi, foo')

 

class Bar(object):

    def bar(self):

        logger.info('Hi, bar')

main.py

Python

1

2

3

4

5

6

7

8

9

10

import logging

 

logger = logging.getLogger(__name__)

 

def foo():

    logger.info('Hi, foo')

 

class Bar(object):

    def bar(self):

        logger.info('Hi, bar')

logging.ini

Python

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

[loggers]

keys=root

 

[handlers]

keys=consoleHandler

 

[formatters]

keys=simpleFormatter

 

[logger_root]

level=DEBUG

handlers=consoleHandler

 

[handler_consoleHandler]

class=StreamHandler

level=DEBUG

formatter=simpleFormatter

args=(sys.stdout,)

 

[formatter_simpleFormatter]

format=%(asctime)s - %(name)s - %(levelname)s - %(message)s

datefmt=

本应该在日志中看到记录,但是你却什么也没有看到。为什么呢?这就是因为你在模块层次创建了 logger,然后你又在加载日志配置文件之前就导入了模块。logging.fileConfig 与 logging.dictConfig 默认情况下会使得已经存在的 logger 失效。所以,这些配置信息不会应用到你的 Logger 上。你最好只在你需要 logger 的时候才获得它。反正创建或者取得 logger 的成本很低。你可以这样写你的代码:

Python

1

2

3

4

5

6

7

8

9

10

11

12

import logging

 

def foo():

    logger = logging.getLogger(__name__)

    logger.info('Hi, foo')

 

class Bar(object):

    def __init__(self, logger=None):

        self.logger = logger or logging.getLogger(__name__)

 

    def bar(self):

        self.logger.info('Hi, bar')

这样,logger 就会在你加载配置后才会被创建。这样配置信息就可以正常应用。

python2.7 之后的版本中 fileConfg 与 dictConfig 都新添加了 “disable_existing_loggers” 参数,将其设置为 False,上面提到的问题就可以解决了。例如:

Python

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

import logging

import logging.config

 

logger = logging.getLogger(__name__)

 

# load config from file

 

# logging.config.fileConfig('logging.ini', disable_existing_loggers=False)

 

# or, for dictConfig

 

logging.config.dictConfig({

    'version': 1,              

    'disable_existing_loggers': False,  # this fixes the problem

 

    'formatters': {

        'standard': {

            'format': '%(asctime)s [%(levelname)s] %(name)s: %(message)s'

        },

    },

    'handlers': {

        'default': {

            'level':'INFO',    

            'class':'logging.StreamHandler',

        },  

    },

    'loggers': {

        '': {                  

            'handlers': ['default'],        

            'level': 'INFO',  

            'propagate': True  

        }

    }

})

 

logger.info('It works!')


【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。