我想使用logging模块代替打印信息和文档调试。目标是在控制台上以DEBUG级别打印并记录到文件中以INFO级别。
我阅读了很多文档,食谱和其他有关logging模块的教程,但无法弄清楚如何按照我想要的方式使用它。(我使用的是python25)
我希望在日志文件中写入日志的模块名称。
文档说我应该使用logger = logging.getLogger(__name__)
,但是我如何声明在其他模块/包中使用的类中使用的记录器,以便它们使用与主记录器相同的处理程序?为了识别“父母”,我可以使用logger = logging.getLogger(parent.child)
,但我怎么知道是谁调用了类/方法?
下面的示例显示了我的问题,如果我运行这个,输出将只有__main__
中的日志,并忽略Class
中的日志
这是我的主文件:
# main.py
import logging
from module import Class
logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)
# create file handler which logs info messages
fh = logging.FileHandler('foo.log', 'w', 'utf-8')
fh.setLevel(logging.INFO)
# create console handler with a debug log level
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
# creating a formatter
formatter = logging.Formatter('- %(name)s - %(levelname)-8s: %(message)s')
# setting handler format
fh.setFormatter(formatter)
ch.setFormatter(formatter)
# add the handlers to the logger
logger.addHandler(fh)
logger.addHandler(ch)
if __name__ == '__main__':
logger.info('Script starts')
logger.info('calling class Class')
c = Class()
logger.info('calling c.do_something()')
c.do_something()
logger.info('calling c.try_something()')
c.try_something()
模块:
# module.py
imnport logging
class Class:
def __init__(self):
self.logger = logging.getLogger(__name__) # What do I have to enter here?
self.logger.info('creating an instance of Class')
self.dict = {'a':'A'}
def do_something(self):
self.logger.debug('doing something')
a = 1 + 1
self.logger.debug('done doing something')
def try_something(self):
try:
logging.debug(self.dict['b'])
except KeyError, e:
logging.exception(e)
在控制台中输出:
- __main__ - INFO : Script starts
- __main__ - INFO : calling class Class
- __main__ - INFO : calling c.do_something()
- __main__ - INFO : calling c.try_something()
No handlers could be found for logger "module"
此外:是否有一种方法可以在不像上面每个类都要声明一个新记录器的情况下,获取日志文件中发生日志的模块名称?另外,像这样,每次想要记录日志时都必须使用self.logger.info()
。我更喜欢在我的整个代码中使用logging.info()
或logger.info()
。也许全局记录器是正确的答案吗?但是我将无法在日志中获取错误发生的模块...
我的最后一个问题:这是否符合Pythonic?还是有更好的建议来正确执行这些操作。
logger.getLogger(__name__)
,那么你将会在日志信息中得到完整的模块名称(包括包的层次结构),前提是你已经设置好了%(name)
格式化元素。请记住,如果根日志器被配置,那么它将应用于所有子日志器(也就是所有包和模块)。 - sirfzlogging.getLogger(__name__)
变量,我该如何编写代码?在我的类中的哪一行需要输入什么? - uloco__name__
,则一切都应该按你想要的方式工作,无需进行任何其他修改(因为您将配置适用于所有子级包括 module.py 的根记录器)。 试一下,你就会明白我的意思了。 - sirfz