手动将 StreamHandler 添加到记录器会破坏 IPython 提示

如何解决手动将 StreamHandler 添加到记录器会破坏 IPython 提示

如果我从 IPython interperter 内的另一个线程登录(使用标准 python 日志记录模块),则提示会针对每个输出的日志移动,如下所示:

In [4]: threading.Thread(target=function_that_logs).start()

ERROR:root:Error message 1
In [5]: i_am_trying_
In [4]: threading.Thread(target=function_that_logs).start()

ERROR:root:Error message 1
ERROR:root:Error message 2
In [5]: i_am_trying_to_type_here

但是,如果我手动添加一个StreamHandler,日志输出不再移动提示。连续记录时,这几乎无法使用提示

In [4]: threading.Thread(target=function_that_logs).start()

In [5]: ERROR:root:Error message 1
i_am_trying_ERROR:root:Error message 2
to_type_here

不同之处似乎是使用了围绕 stdout 的不同包装器,具体取决于创建处理程序的时间/地点。 我尝试查看 IPython 文档,但并没有真正找到任何有用的东西。 如果有人能解释这里发生的事情,或者为我指明正确的方向,我将不胜感激。

请参阅下面的完整工作示例:

> ipython
Python 3.6.8 (tags/v3.6.8:3c6b436a57,Dec 24 2018,00:16:47) [MSC v.1916 64 bit (AMD64)]
Type 'copyright','credits' or 'license' for more information
IPython 7.16.1 -- An enhanced Interactive Python. Type '?' for help.

In [1]: import threading,time,logging

In [2]: def foo():
   ...:     for i in range(15):
   ...:         time.sleep(1)
   ...:         logging.error(f"bar {i}")
   ...:

In [3]: logging.root.handlers
Out[3]: []

In [4]: logging.basicConfig()

In [5]: logging.root.handlers
Out[5]: [<StreamHandler <stderr> (NOTSET)>]

In [3]: logging.root.handlers[0].stream
Out[3]: <colorama.ansitowin32.StreamWrapper at 0x11dc44b9668>

In [7]: threading.Thread(target=foo).start()

In [8]: ERROR:root:bar 0
ERROR:root:bar 1
ERROR:root:bar 2
ERROR:root:bar 3
ERROR:root:bar 4
ERROR:root:bar 5
ERROR:root:bar 6
ERROR:root:bar 7
ERROR:root:bar 8
ERROR:root:bar 9
ERROR:root:bar 10
ERROR:root:bar 11
ERROR:root:bar 12
ERROR:root:bar 13
ERROR:root:bar 14

如果之前没有调用过basicConfig,它会起作用:

> ipython
Python 3.6.8 (tags/v3.6.8:3c6b436a57,logging

In [2]: def foo():
   ...:     for i in range(15):
   ...:         time.sleep(1)
   ...:         logging.error(f"bar {i}")
   ...:

In [3]: logging.root.handlers
Out[3]: []

In [4]: threading.Thread(target=foo).start()

ERROR:root:bar 0
ERROR:root:bar 1
ERROR:root:bar 2
ERROR:root:bar 3
ERROR:root:bar 4
ERROR:root:bar 5
ERROR:root:bar 6
ERROR:root:bar 7
ERROR:root:bar 8
ERROR:root:bar 9
ERROR:root:bar 10
ERROR:root:bar 11
ERROR:root:bar 12
ERROR:root:bar 13
ERROR:root:bar 14
In [5]: logging.root.handlers
Out[5]: [<StreamHandler (NOTSET)>]

In [6]: logging.root.handlers[0].stream
Out[6]: <prompt_toolkit.patch_stdout.StdoutProxy at 0x1321dc82ac8>

编辑:我也尝试手动添加 StdoutProxy,但是我根本没有得到任何输出

> ipython
Python 3.6.8 (tags/v3.6.8:3c6b436a57,logging,prompt_toolkit

In [2]: def foo():
   ...:     for i in range(15):
   ...:         time.sleep(1)
   ...:         logging.error(f"bar {i}")
   ...:

In [3]: logging.root.addHandler(logging.StreamHandler(prompt_toolkit.patch_stdout.StdoutProxy()))

In [4]: threading.Thread(target=foo).start()

In [5]:

EDIT2:我做了更多的实验。似乎存在竞争条件导致不同的流包装器用于标准输出

In [32]: logging.root.handlers = []

In [33]: threading.Thread(target=lambda: time.sleep(1) or logging.basicConfig()).start()

In [34]: logging.root.handlers[0].stream
Out[34]: <prompt_toolkit.patch_stdout.StdoutProxy at 0x20a2f4d1860>

In [35]: logging.root.handlers = []

In [36]: threading.Thread(target=lambda: logging.basicConfig()).start()

In [37]: logging.root.handlers[0].stream
Out[37]: <colorama.ansitowin32.StreamWrapper at 0x20a2e2f9630>

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?