ydf0509 / nb_log

pip install nb_log 各种日志handler和自动转化项目的任意print的效果。日志自动彩色炫酷,可点击控制台的日志自动精确跳转到pycharm的文件和行号。文件日志多进程切割安全。在10个最重要方面全方位超过loguru
389 stars 73 forks source link

日志 io错误 #7

Closed yuluo-zy closed 3 years ago

yuluo-zy commented 3 years ago

hi,您好, 感谢您的 nb_log 的项目, 真的很棒. 但是我在使用中遇到了一些问题, 希望得到您的帮助.

我将nb_log 使用到了 关于 uvicorn 的项目中,

from nb_log import get_logger

logger = get_logger('sys')
app = create_app()

if __name__ == "__main__":
    import uvicorn

    # 输出所有的路由
    for route in app.routes:
        if hasattr(route, "methods"):
            logger.debug({'path': route.path, 'name': route.name, 'methods': route.methods})
    uvicorn.run(app='main:app', host="127.0.0.1", port=7010, reload=True, debug=True)

我在追踪代码中发现 uvicorn.run 代码中

 if config.should_reload:
        sock = config.bind_socket()
        supervisor = ChangeReload(config, target=server.run, sockets=[sock])
        supervisor.run()

config.bin_socket 发生错误,

之后, 我在 bin_socket 中找到以下代码报错

logger.info(
            message,
            protocol_name,
            self.host,
            self.port,
            extra={"color_message": color_message},
        )

报错信息为 valueError i/o operation on closed file.

这里应该是 logger 被替换成了 nb_log 导致的错误.

恳求 您的帮助, 您的项目真的很棒

ydf0509 commented 3 years ago

你说的这个我已经知道,出现这个错误首先是你代码主线程出错了,然后接着就会报这个错误。关键是你代码住线程本身先报错了,才会导致发生后面的日志文件报错,你可以看看报这个错之前的上一个错误堆栈,肯定是其他主线程重要代码报错了,才会导致日志报错。目前tornado uvloop部署我发现的是每次报日志错误,都肯定是先有启动web就出现与日志无关的其他严重错误了,你可以看看上一个报错,只要你把web启动代码搞好了,就不会接着报这个错了。

ydf0509 commented 3 years ago

你把代码发完整,create_app函数发一下,我看能复现不。

yuluo-zy commented 3 years ago

但是, 我确定 其他的是没有错误的.

from nb_log import get_logger

logger = get_logger('sys')

async def app(scope, receive, send):
    assert scope['type'] == 'http'
    await send({
        'type': 'http.response.start',
        'status': 200,
        'headers': [
            [b'content-type', b'text/plain'],
        ]
    })
    await send({
        'type': 'http.response.body',
        'body': b'Hello, world!',
    })

if __name__ == "__main__":
    import uvicorn
    logger.debug("jkhjhh")

    uvicorn.run(app='main:app', host="127.0.0.1", port=7010, reload=True, debug=True)

这是一个简单的实例, 也无法启动

ydf0509 commented 3 years ago

我在linux运行是正常的。 image

yuluo-zy commented 3 years ago

对于配置文件, 我修改了对应的 日志生成文件地址.

LOG_PATH = os.path.join(
    os.path.dirname(os.path.abspath(__file__)),
    'logs'
) 
ydf0509 commented 3 years ago

python版本 win还是linux uvicorn版本,这四个都说一下

yuluo-zy commented 3 years ago

这里应该是开始进行监听, 而不是 停止, python 3.8, win平台, uvicorn版本 是0.13.4

ydf0509 commented 3 years ago

对于配置文件, 我修改了对应的 日志生成文件地址.

LOG_PATH = os.path.join(
    os.path.dirname(os.path.abspath(__file__)),
    'logs'
) 

你get_logger没有指定file_name,默认为了节约磁盘和代码性能是不会自动生成日志文件的。只有指定了文件名才会生成日志文件。你光配路径没用。

ydf0509 commented 3 years ago

这里应该是开始进行监听, 而不是 停止, python 3.8, win平台, uvicorn版本 是0.13.4

uvicorn不支持windows会报错。在linux 保证没问题

ydf0509 commented 3 years ago

这个很容易测试,

把
logger = nb_log.get_logger('sys')
换成官方日志
logger = logging.getLogger("sys")
照样会报错的
ydf0509 commented 3 years ago

与nb_log无关,uvicorn要在linux运行

ydf0509 commented 3 years ago

python很多包都不是跨平台的,只有mac和linux才会运行好,win不行

yuluo-zy commented 3 years ago

可是如果我不加日志的话,就可以运行进行监听,

获取 Outlook for iOShttps://aka.ms/o0ukef


发件人: ydf0509 @.> 发送时间: Wednesday, July 7, 2021 12:13:50 PM 收件人: ydf0509/nb_log @.> 抄送: yuluo @.>; Author @.> 主题: Re: [ydf0509/nb_log] 日志 io错误 (#7)

python很多包都不是跨平台的,只有mac和linux才会运行好,win不行

― You are receiving this because you authored the thread. Reply to this email directly, view it on GitHubhttps://github.com/ydf0509/nb_log/issues/7#issuecomment-875261392, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AIBUWX3IJTX77QLEGJTKTSDTWPH75ANCNFSM475ZFJPQ.

ydf0509 commented 3 years ago

image 这是win的python解释器运行的会出错,linux的python解释器不会出错

yuluo-zy commented 3 years ago

可能您忽略了文件名称,

uvicorn.run(app='main:app', host="127.0.0.1", port=7010, reload=True, debug=True)

这里的main 是文件的名称

正常运行情况应该是如下:

image

其 uv 开始在 7010端口上进行监听, 这是没有添加 log的实况.

当我解除 关于log的注释后, 会出现如下情况

image

进程会自动被结束掉, 此时并没有任何的报错信息出现, 需要您手工去 uvicorn.run 中打断点调试

最终的捕获结果如图所示

image

这是一个干净的环境, 只安装了 uv 和 nblog, 完整代码如下:

# 这是一个示例 Python 脚本。

# 按 Shift+F10 执行或将其替换为您的代码。
# 按 双击 Shift 在所有地方搜索类、文件、工具窗口、操作和设置。

from nb_log import get_logger

logger = get_logger('sys')

async def app(scope, receive, send):
    assert scope['type'] == 'http'
    await send({
        'type': 'http.response.start',
        'status': 200,
        'headers': [
            [b'content-type', b'text/plain'],
        ]
    })
    await send({
        'type': 'http.response.body',
        'body': b'Hello, world!',
    })

if __name__ == "__main__":
    import uvicorn

    logger.debug("jkhjhh")

    uvicorn.run(app='test:app', host="127.0.0.1", port=7010, reload=True, debug=True)

文件名称为 test.py

确实是一个很隐蔽的错误. 这应该和平台无关, uv 虽然确实对win 支持不友好, 但是当前简单的demo 应该没有太大影响

yuluo-zy commented 3 years ago

python 版本上面说错了, 应该是3.9 的版本, 如果3.8 版本包没有问题, 可以降到3.8

ydf0509 commented 3 years ago

和python版本无关,和平台有关,上linux就行。什么uwsgi gunicorn uvloop uvicorn 统一用linux就是了

yuluo-zy commented 3 years ago

我试一下

ydf0509 commented 3 years ago

image 是模块的名字没写好,现在模块文件名字改好了。windows没出错

ydf0509 commented 3 years ago

另外你的pycahrm要按我说的调一下主题颜色代码的,控制台的打印输出,已近教你怎么设置了,你现在颜色太丑了。

yuluo-zy commented 3 years ago

image

这是它的报错堆栈信息, 但是您那边能运行, 我这里就不可以, 复现不出来, 确实有点绝望....

yuluo-zy commented 3 years ago

我尝试降低版本试一下

yuluo-zy commented 3 years ago

您好, 已经确定在3.6 版本运行无异常信息, 可以正常使用, 此为版本兼容性问题.

感谢您的帮助

yuluo-zy commented 3 years ago

现在 我修改了部分代码, 来临时解决这个问题 在 def revision_call_handlers 中 修改

 while c:
        for hdlr in c.handlers:
            hdlr_type = type(hdlr)
            if hdlr_type == logging.StreamHandler:
                # 这里的streamhandler 的转换有问题, 现在只临时修改
                hdlr.close()
                hdlr = ColorHandler()
            found = found + 1
            if record.levelno >= hdlr.level:
                if hdlr_type not in hdlr_type_set:
                    hdlr.handle(record)
                hdlr_type_set.add(hdlr_type)
        if not c.propagate:
            c = None  # break out
        else:
            c = c.parent

当前方案存在stream 流关闭的问题,

ydf0509 commented 3 years ago

这样肯定不行吧,你关了还能打印日志吗

yuluo-zy commented 3 years ago

image

关掉原来的 , 使用你 ColorHandler init 中初始化的, 但是这样的话都转换成了 sys.stdout

yuluo-zy commented 3 years ago

比如 原来是 sys.stderror的 都转化成了 stdout了, nb_log 的库文件我还没有研读, 肯定存在更好的方法的

yuluo-zy commented 3 years ago

这样临时解决了 io 流关闭的问题

ydf0509 commented 3 years ago

比如 原来是 sys.stderror的 都转化成了 stdout了, nb_log 的库文件我还没有研读, 肯定存在更好的方法的

日志原本是stderr所以是那种灰红色的。如果我不让日志使用stdout,用stderr就只能是灰红色,实现不了五彩色。我之前试过用stderr,但是那样实现不了彩色,变成了统一灰红色。

yuluo-zy commented 3 years ago

您 最开始 使用

if hdlr_type == logging.StreamHandler:
 hdlr_type = ColorHandler

这里没有懂 为什么这么操作

ydf0509 commented 3 years ago
这里是一个判断,要精通日志命名空间的作用的人才能通,你可以用原生logging测试,比如 
logger1=logging.getLogger(”a.b")  logger1.addStreahndler(或者filehandler等),命名空间加了handler,
logger2=logging.getLogger(”a")命名空间也加了addStreahandler,那么你是使用 logger1.debug("hello"),
控制台会打印两次的,命名空间是.隔开的,一直往上找。而且根日志是所有日志的父命名空间,

如果你在根日志加了streamdnler,在单独name上也加stramhndler,也会重复打印两次。这个作用是确保任何种类的handler只记录一次。
if hdlr_type == logging.StreamHandler:
 hdlr_type = ColorHandler

至于这个,因为filehandler等一切任意handler都是集成自StreamHandler的, hdlr_type = ColorHandler可以写成任意类名,主要是用于set过滤。你用isinstance(filehandler,Streamhndler)也是True的,因为任何其他handler都是Streamhdnler的子类
yuluo-zy commented 3 years ago

明白了, 感谢您的帮助!!