V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
kier
V2EX  ›  Python

关于 python 写 log 的一个疑问

  •  
  •   kier · 2016-11-08 10:47:45 +08:00 · 5168 次点击
    这是一个创建于 2924 天前的主题,其中的信息可能已经有所发展或是发生改变。
    python 自带的 logging 模块虽然有 timerotate ,但是它是把当前 log 文件重命名,然后再开新文件,这样的话,就容易会出现多 process 冲突的问题!
    所以楼主在上家公司时,是用的从 logging 模块扩展的模块,具体实现是每小时一个日志文件(文件名里包含时间信息),各个 process 都 append 方式打开写入,当前小时的 log 写完了,自动用 append 方式打开下一个日志文件,这样就不存在重命名的问题,也不会有多 process 冲突的问题。
    最近做项目,还是想用这种方式,但是换了东家,原来的代码没找到,所以想网上找,结果一点相关的都没找到,难道就没人这么用的吗?那大家是如何处理写 log ,多 process 的问题呢?都用 sockethandler ,让一个单独的服务去同一写日志?
    19 条回复    2016-11-09 20:13:13 +08:00
    iyaozhen
        1
    iyaozhen  
       2016-11-08 11:00:34 +08:00 via Android
    这就是两种打日志的风格了。
    一种是 access.log
    一种是 access.log.2016110810
    看日志框架的类型了,一般都支持自己滚动日志。
    不过一般第一种用的多, op 会自己配置日志切分程序,先 mv 重命名日志,然后再给写日志的进程发一个啥信号,然后程序会自动在原来的位置再起一个新文件打日志。
    knightdf
        2
    knightdf  
       2016-11-08 11:08:58 +08:00
    python 自带的 TimedRotatingFileHandler 本来就在多进程下有 bug,会误删日志.得自己重写 doRollover 函数
    doer233
        3
    doer233  
       2016-11-08 11:10:26 +08:00 via Android
    python 新手请教个问题,生产项目的 log 代码直接写在生产代码里面吗?
    lostarray
        4
    lostarray  
       2016-11-08 12:48:36 +08:00 via iPhone   ❤️ 2
    如果是在 Linux 下,可以考虑用 syslog 和 logrotate
    onlyice
        5
    onlyice  
       2016-11-08 12:50:14 +08:00
    Python 的官方文档有提到这个问题: https://docs.python.org/3/howto/logging-cookbook.html#logging-to-a-single-file-from-multiple-processes

    QueueHandler 可以解决这个问题。它是在 Python 3 中加入的; Python 2 中没有,但是也可以搜到类似代码。
    yanchao7511461
        6
    yanchao7511461  
       2016-11-08 13:13:15 +08:00
    借楼问个问题
    一般 python 的 traceback 是出错定位的重要信息。但是一个程序里面 我又不想用 try... 能不能想办法把这个错误信息保存下来。看到具体哪行出错。 是不是除了 2 >&1 没办法了?
    onlyice
        7
    onlyice  
       2016-11-08 15:16:17 +08:00 via Android
    @yanchao7511461 logging 里面的 logger.exception 函数
    yanchao7511461
        8
    yanchao7511461  
       2016-11-08 19:32:10 +08:00
    @onlyice 不太明白怎么用...我用 logger 一般都是 try 。。。。 excetion logger.error(" xxx error !!").都是通过 try 然后输出信息的... 所以一旦我的程序后台运行的,某一个我没想到的位置崩溃了。我就看不到 traceback 了.... 能给个例子 说一下 logger.exception 怎么用么
    onlyice
        9
    onlyice  
       2016-11-08 19:39:54 +08:00   ❤️ 1
    @yanchao7511461 啊,我读题没读仔细。。

    logger.exception 函数可以把 traceback 也打印下来。

    但是对于未捕获的异常,你可以修改 sys.excepthook 来自定义行为: https://docs.python.org/2/library/sys.html#sys.excepthook

    但是我不确定是不是好的实践。。感觉可以看看 Sentry 怎么做
    kier
        10
    kier  
    OP
       2016-11-08 20:47:46 +08:00
    @knightdf 嗯,如果按照我帖子里描述的方法,多进程也是没有问题的,只是我在网上居然没有发现有哪怕一个人是用这种方式的,所以觉得很诧异!因为我的理解,对于中小型项目,这种方法的开发运维成本是最低的!
    kier
        11
    kier  
    OP
       2016-11-08 20:51:10 +08:00   ❤️ 1
    @yanchao7511461 @onlyice 无法预知的 exception 没有必要自己去 try catch ,就让它落到 stderr 就 ok 了,而对于服务端程序这类需要常驻运行的,一般在最外层会捕获异常,并输出的
    onlyice
        12
    onlyice  
       2016-11-08 21:34:18 +08:00
    @kier 嗯是的,只是 @yanchao7511461 的场景是他不想去 try catch ,所以可能 sys.excepthook 有作用
    fengclient
        13
    fengclient  
       2016-11-08 22:35:09 +08:00 via iPhone
    同意上面说的 syslog/rsyslog ,可以很好解决多点写入的问题,这也是大型系统的标准操作吧。
    knightdf
        14
    knightdf  
       2016-11-08 23:40:57 +08:00
    @kier 只要有新文件产生,append 必然也会有问题,因为问题就出在谁来产生这个新文件这.
    ericls
        15
    ericls  
       2016-11-09 01:44:35 +08:00
    用个 queue 来专门写日志
    restran
        16
    restran  
       2016-11-09 08:39:17 +08:00
    kier
        17
    kier  
    OP
       2016-11-09 10:25:20 +08:00
    @knightdf 用 append 的方式 open 文件,应该没问题吧, open 应该是 atomic 操作吧
    zjq426
        18
    zjq426  
       2016-11-09 16:03:25 +08:00
    @kier https://github.com/zhujiaqi/pycrabapi/tree/master/miscs/logger

    我前前东家的项目里面刚好也有这个东西,在前前同事们的授意下我给他开源了
    heqingpan
        19
    heqingpan  
       2016-11-09 20:13:13 +08:00
    @kier
    http://www.cnblogs.com/shizioo/p/python_logging_handler_custom.html
    ---
    import logging
    import os,os.path
    import datetime

    _filefmt=os.path.join("logs","%Y-%m-%d","%H.log")
    class MyLoggerHandler(logging.Handler):
    def __init__(self,filefmt=None):
    self.filefmt=filefmt
    if filefmt is None:
    self.filefmt=_filefmt
    logging.Handler.__init__(self)
    def emit(self,record):
    msg=self.format(record)
    _filePath=datetime.datetime.now().strftime(self.filefmt)
    _dir=os.path.dirname(_filePath)
    try:
    if os.path.exists(_dir) is False:
    os.makedirs(_dir)
    except Exception:
    print "can not make dirs"
    print "filepath is "+_filePath
    pass
    try:
    _fobj=open(_filePath,'a')
    _fobj.write(msg)
    _fobj.write("\n")
    _fobj.flush()
    _fobj.close()
    except Exception:
    print "can not write to file"
    print "filepath is "+_filePath
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2681 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 08:18 · PVG 16:18 · LAX 00:18 · JFK 03:18
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.