重定向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

python logging 重定向print(标准输入输出)的更多相关文章

  1. python logging 替代print 输出内容到控制台和重定向到文件

    转自:http://blog.csdn.net/z_johnny/article/details/50740528

  2. python学习第二天标准输入输出和注释用法

    任何编程语言都有输入输出和用打交道,python也不例外,输入input(),输出print() 玖乐网络(http://www.96net.com.cn/)分享自己的心得 1,input()用法实例 ...

  3. python logging—模块

    python logging模块 python logging提供了标准的日志接口,python logging日志分为5个等级: debug(), info(), warning(), error( ...

  4. 从使用os.system)在python命令(重定向标准输入输出

    从使用os.system)在python命令(重定向标准输入输出 python 标准输出stdout stdio os.system通常我可以通过改变sys.stdout的值在python更改标准输出 ...

  5. Python学习笔记015——文件file的常规操作之三(标准输入输出文件)

    1 标准输入输出文件 在Python中,模块sys中含有标准的输入输出文件 sys.stdin     标准输入方法(一般是键盘) sys.stdout   标准输出方法(到显示器的缓冲输出) sys ...

  6. Python基础笔记系列十一:标准输入输出、文件读写和指针等操作

    本系列教程供个人学习笔记使用,如果您要浏览可能需要其它编程语言基础(如C语言),why?因为我写得烂啊,只有我自己看得懂!! 标准输入输出一.输入 在sublime中这个时候需要安装SublimeRE ...

  7. C/C++ 标准输入输出重定向

    转载自:http://www.cnblogs.com/hjslovewcl/archive/2011/01/10/2314356.html 这个对经常在OJ上做题的童鞋们很有用.OJ基本都是用标准输入 ...

  8. 【转载】标准输入输出重定向(Visual C++)

    原文:标准输入输出重定向(Visual C++) 引言 本人偶得在 Visual C++ 中进行输入输出重定向的办法,比通常的做法“freopen”更加的灵活和方便,特在此共享.目前,代码正在不断地摸 ...

  9. linux标准输入输出与重定向

    原文:http://blog.sina.com.cn/s/blog_8333cf8f0100vzzl.html##1 1. 标准输入输出和错误    linux下使用标准输入文件stdin和标准输出文 ...

随机推荐

  1. 15 SpringMVC的入门案例

    1.入门程序的需求 2.搭建开发环境 <1>Create New Project <2>创建一个webapps <3>设置maven路径和解决maven项目创建过慢 ...

  2. [转帖]使用fastdfs搭建文件管理系统

    使用fastdfs搭建文件管理系统 https://www.jianshu.com/p/4e80069c84d3 今天同事说他们的系统用到了这个分布式文件管理系统. 一.FastDFS介绍 FastD ...

  3. 【C++札记】虚继承

    由于多重继承产生的二义性引入了类的虚继承,先看下什么是二义性. 类D是类B和类C的派生类,而类B,类C就是继承于类A,当D调用类A中的函数时不知道是类B继承A的,还是类C继承A的,引起了二义性.虚继承 ...

  4. Python解释器安装与环境变量添加

    Python解释器安装与环境变量添加 Python解释器安装(3.6和2.7): www.python.org这个是python解释器的官网,一定要牢记. 鉴于市场上有两种python版本(2和3), ...

  5. Java 总结篇2

    第02章:数据类型和运算符 一.概述: 1.数据类型:int.float.char.boolean 2.运算符:算术运算符.赋值运算符.关系运算符.逻辑运算符.位运算符(了解即可).条件运算符 3.基 ...

  6. golang数组

  7. leetcode整数反转

    给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转. 示例 1: 输入: 123输出: 321 示例 2: 输入: -123输出: -321 示例 3: 输入: 120输出: 21 ...

  8. centos7简单部署rancher

    rancher官网文档地址 https://www.cnrancher.com/docs/rancher/v2.x/cn/overview/ 准备机器 两台虚拟机 192.168.56.100 192 ...

  9. 面试4 --- constructor必须与class同名,但方法不能与class同名?

    选 C “constructor必须与class同名,但方法不能与class同名”这句话是错误的,方法是可以和class同名的:方法可以和类名同名的,和构造方法唯一的区别就是,构造方法没有返回值.

  10. LOJ2074/2157 JSOI2016/POI2011 Lightning Conductor 决策单调性DP

    传送门 我们相当于要求出\(f_i = \max\limits_{j=1}^{n} (a_j + \sqrt{|i-j|})\).这个绝对值太烦人了,考虑对于\(i>j\)和\(i<j\) ...