Python:日志模块-全局

Python:日志模块-全局,python,logging,module,global-variables,Python,Logging,Module,Global Variables,我想知道如何实现一个全局记录器,可以在任何地方使用您自己的设置: 我目前有一个自定义记录器类: class customLogger(logging.Logger): ... 该类位于一个单独的文件中,其中包含一些格式化程序和其他内容。 记录器可以自己完美地工作 我在主python文件中导入此模块,并创建如下对象: self.log = logModule.customLogger(arguments) Project/ |-- .../ | |-- ... | |-- proje

我想知道如何实现一个全局记录器,可以在任何地方使用您自己的设置:

我目前有一个自定义记录器类:

class customLogger(logging.Logger):
   ...
该类位于一个单独的文件中,其中包含一些格式化程序和其他内容。 记录器可以自己完美地工作

我在主python文件中导入此模块,并创建如下对象:

self.log = logModule.customLogger(arguments)
Project/
|-- .../
|   |-- ...
|
|-- project/
|   |-- package/
|   |   |-- __init__.py
|   |   |-- module.py
|   |   
|   |-- __init__.py
|   |-- project.py
|
|-- ...
|-- ...
import logging
...
log = logging.getLogger(__name__)

class ModuleClass:
    def do_something(self):
        log.debug('do_something() has been called!')
import logging
from project import App

def setup_logger():
    # create logger
    logger = logging.getLogger('project')
    logger.setLevel(logging.DEBUG)

    # create console handler and set level to debug
    ch = logging.StreamHandler()
    ch.setLevel(level)

    # create formatter
    formatter = logging.Formatter('%(asctime)s [%(levelname)s] %(name)s: %(message)s')

    # add formatter to ch
    ch.setFormatter(formatter)

    # add ch to logger
    logger.addHandler(ch)

if __name__ == '__main__' and __package__ is None:
     setup_logger()
     app = App()
     app.do_some_funny_stuff()
但显然,我无法从代码的其他部分访问此对象。
我是否使用了错误的方法?有更好的方法吗?

在日志模块中创建一个
customLogger
的实例,并将其作为一个单例使用-只需使用导入的实例,而不是类。

您只需在第一个句点之前传递一个带有公共子字符串的字符串即可。字符串中以句号(“.”)分隔的部分可用于不同的类/模块/文件等,例如(特别是
logger=logging.getLogger(loggerName)
part):

def getLogger(名称,logdir=logdir\u默认值,level=logging.DEBUG,logformat=FORMAT):
base=os.path.basename(_文件__)
loggerName=“%s.%s”%(基本,名称)
logFileName=os.path.join(logdir,“%s.log”%loggerName)
logger=logging.getLogger(loggerName)
logger.setLevel(级别)
i=0
当os.path.exists(logFileName)而不是os.access(logFileName,os.R_OK | os.W_OK)存在时:
i+=1
logFileName=“%s.%s.log”%(logFileName.replace(“.log”),str(i).zfill((len(str(i))+1)))
尝试:
#fh=logging.FileHandler(logFileName)
fh=RotatingFileHandler(filename=logFileName,mode=“a”,maxBytes=1310720,backupCount=50)
除IOError外,exc:
errOut=“无法创建/打开日志文件\%s\”“%logFileName”
如果exc.errno为13:#权限被拒绝异常
errOut=“ERROR**权限被拒绝**-%s”%errOut
elif exc.errno是2:#没有这样的目录
errOut=“ERROR**没有这样的目录\%s\”***-%s”%(os.path.split(logFileName)[0],errOut)
elif exc.errno为24:#打开的文件太多
errOut=“ERROR**打开的文件太多**-检查/proc//fd/(PID:%s)“%os.getpid()中的打开文件描述符
其他:
errOut=“未处理的异常**%s**-%s”%(str(exc),errOut)
引发日志异常(errOut)
其他:
格式化程序=日志记录。格式化程序(logformat)
fh.设置电平(电平)
fh.设置格式化程序(格式化程序)
logger.addHandler(fh)
返回记录器
类主线程:
定义初始化(self、cfgdefaults、configdir、pidfile、logdir、test=False):
self.logdir=logdir
logLevel=logging.DEBUG
logPrefix=“MainThread\u TEST”如果self.TEST或“MainThread”
尝试:
self.logger=getLogger(logPrefix,self.logdir,logLevel,FORMAT)
除LogException外,exc:
sys.stderr.write(“%s\n”%exc)
sys.stderr.flush()
操作系统退出(0)
其他:
self.logger.debug(“--------------已创建主线程。正在启动\uuuu init\uuuuu()--------------”)
def运行(自):
self.logger.debug(“初始化ReportThreads….”)
对于self.config.items()中的(group,cfg):
self.logger.debug(“-------------------------------------组“%s”配置-----------------------------------------------”%GROUP)
对于cfg.items()中的k2和v2:
self.logger.debug(“%s%s:%s”%(组,k2,v2))
尝试:
rt=ReportThread(self、group、cfg、self.logdir、self.test)
除LogException外,exc:
sys.stderr.write(“%s\n”%exc)
sys.stderr.flush()
self.logger.exception(“创建ReportThread(%s)”时出现异常%group)
logging.shutdown()
操作系统退出(1)
其他:
self.threads.append(rt)
self.logger.debug(“线程已初始化..\%s\”“%”,“.join([t.name代表self.Threads中的t]))
对于self.threads中的t:
t、 开始()
如果不是自检:
self.loop()
类报告线程:
def _uinit _;(self,mainThread,name,config,logdir,test):
self.mainThread=mainThread
self.name=名称
logLevel=logging.DEBUG
self.logger=getLogger(“主线程%s.ReportThread_%s”%(“如果self.TEST else,则为_TEST”),logdir,logLevel,FORMAT)
self.logger.info(“初始化数据库…”)
self.initDB()
#等等。。。。
如果名称=“\uuuuu main\uuuuuuuu”:
# .....
主线程(cfgdefaults=options.cfgdefaults,configdir=options.configdir,pidfile=options.pidfile,logdir=options.logdir,test=options.test)
用于创建命名的全局记录器

main.py

log.py

子模块.py

输出

2011-10-01 20:08:40,049 - DEBUG - main - main message
2011-10-01 20:08:40,050 - DEBUG - submodule - submodule message

由于我还没有找到一个令人满意的答案,因此我想对这个问题的答案做一点详细说明,以便深入了解Python标准库附带的
日志记录
库的工作原理和意图

与OP(原始海报)的方法不同,该库清楚地将记录器的接口和记录器本身的配置分开

处理程序的配置是使用库的应用程序开发人员的特权

这意味着您不应该创建自定义记录器类并通过添加任何配置或其他方式在该类内配置记录器

logging
库引入了四个组件:记录器、处理程序、过滤器和格式化程序

  • 记录器公开应用程序代码直接使用的接口
  • 处理程序将日志记录(由记录器创建)发送到相应的目标
  • 过滤器提供了更细粒度的工具,用于确定要输出哪些日志记录
  • 格式化程序指定最终输出中日志记录的布局
共同项目
2011-10-01 20:08:40,049 - DEBUG - main - main message
2011-10-01 20:08:40,050 - DEBUG - submodule - submodule message
Project/
|-- .../
|   |-- ...
|
|-- project/
|   |-- package/
|   |   |-- __init__.py
|   |   |-- module.py
|   |   
|   |-- __init__.py
|   |-- project.py
|
|-- ...
|-- ...
logger = logging.getLogger(__name__)
import logging
...
log = logging.getLogger(__name__)

class ModuleClass:
    def do_something(self):
        log.debug('do_something() has been called!')
import logging
from project import App

def setup_logger():
    # create logger
    logger = logging.getLogger('project')
    logger.setLevel(logging.DEBUG)

    # create console handler and set level to debug
    ch = logging.StreamHandler()
    ch.setLevel(level)

    # create formatter
    formatter = logging.Formatter('%(asctime)s [%(levelname)s] %(name)s: %(message)s')

    # add formatter to ch
    ch.setFormatter(formatter)

    # add ch to logger
    logger.addHandler(ch)

if __name__ == '__main__' and __package__ is None:
     setup_logger()
     app = App()
     app.do_some_funny_stuff()
import logging
logging.basicConfig(level = logging.DEBUG,format = '[%(asctime)s] %(levelname)s [%(name)s:%(lineno)s] %(message)s')
import logging
logger = logging.getLogger(__name__)
logger.info('hello world!')
logging.config.fileConfig("logging.conf")