zoukankan      html  css  js  c++  java
  • python logging 重定向print(标准输入输出)

    重定向print输出到Mongo

    celery 本身用到logging.info 会输出
    是celery的问题,还是logging初始化的时候就会有输出?
    好像是celery 配合logging的问题
    
    不同位置不同地方的```logging.getLogger(logname)```,只要logname相同,就会获取到同一个日志logging。它们设置的handler是同享的。
    可以理解为,logging名相同则注册在内存里,每次getLogger时,内存里有就指向它,没有就新建一个。
    也就是说,第一个logging.getLogger("MyLogging")设置了handler后,第二处调用logging.getLogger("MyLogging")时拿到的logging已经有handler了。如果每次初始化logging都加句柄,就会导致该句柄重复添加,重复输出。
    可以通过查看该logging的handler的方式,判断还加不加。没有就加,有就算了。
    class Logger(object):
        def __init__(self, logname="ScanDeault"):
            self.logger = logging.getLogger(logname)
            self.logger.setLevel(logging.DEBUG)
    
        def getScanLogger(self):
            if self.logger.handlers:
                return self.logger
            mon = MongoHandler(url=MONGO_SCAN_URL, database_name=MONGO_SCAN_DATABASE)
            mon.setLevel(logging.WARN)
            # ch = logging.StreamHandler()
            # fmt = logging.Formatter('[%(asctime)s][%(levelname)-5s] %(funcName)s(%(lineno)d) : %(message)s',
            #                         "%Y-%m-%d %H:%M:%S")
            # ch.setFormatter(fmt)
            # ch.setLevel(logging.INFO)
            self.logger.addHandler(mon)
            # self.logger.addHandler(ch)
            return self.logger
    
    这里注意,如果在其他地方把这个logname添加了个ERROR的handler,会导致这里的handler加不上了,handler失效
    
    class MongoHandler(logging.Handler):
        def __init__(self, level=logging.NOTSET, url=None, host='localhost', port=27017,
                     database_name='logs', collection='t_logs',
                     username=None, password=None, authentication_db='admin',
                     fail_silently=False, formatter=None, capped=False,
                     capped_max=1000, capped_size=1000000, reuse=True, **kwargs):
            """
            Setting up mongo handler, initializing mongo database connection via
            pymongo.
    
            If reuse is set to false every handler will have it's own MongoClient.
            This could hammer down your MongoDB instance, but you can still use
            this option.
    
            The default is True. As such a program with multiple handlers
            that log to mongodb will have those handlers share a single connection
            to MongoDB.
            """
            logging.Handler.__init__(self, level)
            self.url = url  # changed, 新增MongoDB连接方式
            self.host = host
            self.port = port
            self.database_name = database_name
            self.collection_name = collection
            self.username = username
            self.password = password
            self.authentication_database_name = authentication_db
            self.fail_silently = fail_silently
            self.connection = None
            self.db = None
            self.collection = None
            self.authenticated = False
            self.formatter = formatter or MongoFormatter()
            self.capped = capped
            self.capped_max = capped_max
            self.capped_size = capped_size
            self.reuse = reuse
            self._connect(**kwargs)
    
        def _connect(self, **kwargs):
            """Connecting to mongo database."""
            global _connection
            if self.reuse and _connection:
                self.connection = _connection
            else:
                if pymongo.version_tuple[0] < 3:
                    try:
                        if self.url:
                            self.connection = Connection(self.url)
                        else:
                            self.connection = Connection(host=self.host,
                                                         port=self.port, **kwargs)
                    # pymongo >= 3.0 does not raise this error
                    except PyMongoError:
                        if self.fail_silently:
                            return
                        else:
                            raise
                else:
                    if self.url:
                        self.connection = Connection(self.url)
                    else:
                        self.connection = Connection(host=self.host, port=self.port, **kwargs)
                    try:
                        self.connection.is_primary
                    except ServerSelectionTimeoutError:
                        if self.fail_silently:
                            return
                        else:
                            raise
                _connection = self.connection
    
            self.db = self.connection[self.database_name]
            if self.username is not None and self.password is not None:
                auth_db = self.connection[self.authentication_database_name]
                self.authenticated = auth_db.authenticate(self.username,
                                                          self.password)
    
            if self.capped:
                #
                # We don't want to override the capped collection
                # (and it throws an error anyway)
                try:
                    self.collection = Collection(self.db, self.collection_name,
                                                 capped=True, max=self.capped_max,
                                                 size=self.capped_size)
                except OperationFailure:
                    # Capped collection exists, so get it.
                    self.collection = self.db[self.collection_name]
            else:
                self.collection = self.db[self.collection_name]
    
        def close(self):
            """
            If authenticated, logging out and closing mongo database connection.
            """
            if self.authenticated:
                self.db.logout()
            if self.connection is not None:
                self.connection.close()
    
        def emit(self, record):
            """Inserting new logging record to mongo database."""
            if self.collection is not None:
                try:
                    if os.path.basename(__file__) not in record.pathname:
                        getattr(self.collection, write_method)(self.format(record))
                except Exception:
                    if not self.fail_silently:
                        self.handleError(record)
    
    class MyLogger(object):
        def __init__(self, logname="MyRePrint"):
            self.logger = logging.getLogger(logname)
            self.logger.setLevel(logging.DEBUG)
            if not self.logger.handlers:
                mon = MongoHandler(url=MONGO_SCAN_URL, database_name=MONGO_SCAN_DATABASE)
                mon.setLevel(logging.INFO)   # print为INFO级别
                ch = logging.StreamHandler()
                ch.setFormatter(logging.Formatter('[%(asctime)s][%(levelname)-5s] %(funcName)s(%(lineno)d) : %(message)s',
                                                  "%Y-%m-%d %H:%M:%S"))
                ch.setLevel(logging.INFO)
                self.logger.addHandler(ch)
                self.logger.addHandler(mon)
    
        def write(self, message):
            if message.strip():
                self.logger.info(message)
    
    if __name__ == '__main__':
        original_stdout = sys.stdout
        sys.stdout = PluginLogger(logname="MyRePrint")
        print 1
        sys.stdout = original_stdout
    
    
  • 相关阅读:
    [转]ASP.NET中JSON的序列化和反序列化
    [转]JavaScriptSerializer中日期序列化
    [转]国外英语教学网页
    [转]linq to sql (Group By/Having/Count/Sum/Min/Max/Avg操作符)
    [转]Business Model Canvas(商业模式画布):创业公司做头脑风暴和可行性测试的一大利器
    [转]sql server transaction
    CentOS7安装配置PostgreSQL9.6
    使用struts的同步令牌避免form的重复提交
    Flink初探-为什么选择Flink
    jdbc三种常见用法
  • 原文地址:https://www.cnblogs.com/huim/p/11856173.html
Copyright © 2011-2022 走看看