python logging 重定向print(标准输入输出)

时间:2019-11-14
本文章向大家介绍python logging 重定向print(标准输入输出),主要包括python logging 重定向print(标准输入输出)使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

重定向print输出到Mongo

不同位置不同地方的```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

原文地址:https://www.cnblogs.com/huim/p/11856173.html