- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章Python 解决logging功能使用过程中遇到的一个问题由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
生产中心进行拷机任务下了300个任务,过了一阵时间后发现任务不再被调度起来,查看后台日志发现日志输出停在某个时间点.
1、首先确认进程存在并没有dead.
2、然后用strace –p看了一下进程,发现进程卡在futex调用上面,应该是在锁操作上面出问题了.
3、用gdb attach进程ID,用py-bt查看一下堆栈,发现堆栈的信息大致为:sig_handler(某个信号处理函数)->auroralogger(自定义的日志函数)->logging(python的logging模块)->threading.acquire(获取锁)。从gdb的bt信息基本验证了上面的猜想,应该是出现了死锁.
4、Python的logging模块本身肯定不会有死锁的这种bug有可能出问题的就是我们的使用方式,看python中logging模块的doc,发现有一个有一个Thread Safety的章节,内容很简单但是也一下就解释了我遇到的这个问题,内容如下:
The logging module is intended to be thread-safe without any special work needing to be done by its clients. It achieves this though using threading locks; there is one lock to serialize access to the module's shared data, and each handler also creates a lock to serialize access to its underlying I/O. 。
If you are implementing asynchronous signal handlers using the signal module, you may not be able to use logging from within such handlers. This is because lock implementations in the threading module are not always re-entrant, and so cannot be invoked from such signal handlers. 。
第一部分是说logging是线程安全的,通过threading的lock对公用的数据进行了加锁.
第二部分特意提到了在异步的信号处理函数中不能使用logging模块,因为threading的lock机制是不支持重入的.
这样就解释了上面我遇到的死锁问题,因为我在信号处理函数中调用了不可以重入的logging模块.
从上面的logging模块来看线程安全和可重入不是等价的,那么这两个概念之间有什么联系、区别呢?
1、可重入函数:从字面意思来理解就是这个函数可以重复调用,函数被多个线程乱序执行甚至交错执行都能保证函数的输出和函数单独被执行一次的输出一致。也就是说函数的输出只决定于输入.
线程安全函数:函数可以被多个线程调用,并且保证不会引用到错误的或者脏的数据。线程安全的函数输出不仅仅依赖于输入还可能依赖于被调用时的顺序.
2、可重入函数和线程安全函数之间有一个最大的差异是:是否是异步信号安全。可重入函数在异步信号处理函数中可以被安全调用,而线程安全函数不保证可以在异步信号处理函数中被安全调用.
上面我们遇到的loggin模块就是非异步信号安全的,在主线程中我们正在使用log函数而log函数调用了threading.lock来获取到了锁,此时一个异步信号产生程序跳转到信号处理函数中,信号处理函数又正好调用了log函数,因为前一个被调用的log函数还未释放锁,最后就形成了一个死锁.
1、可重入函数必然是线程安全函数和异步信号安全函数,线程安全函数不一定是可重入函数.
异步信号处理函数中一定要尽可能的功能简单并且不能调用不可重入的函数.
Python loggin模块是线程安全但是是不可重入的.
补充:Python—logging模块使用教程 。
级别 | 何时使用 |
---|---|
DEBUG | 细节信息,仅当诊断问题时适用。 |
INFO | 确认程序按预期运行 |
WARNING | 表明有已经或即将发生的意外(例如:磁盘空间不足)。程序仍按预期进行 |
ERROR | 由于严重的问题,程序的某些功能已经不能正常执行 |
CRITICAL | 严重的错误,表明程序已不能继续执行 |
1
2
3
|
import
logging
logging.warning(
'Watch out!'
)
logging.info(
'I told you so'
)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
import
logging
# 保存文件为example.log,记录等级为DEBUG,即只记录DENBUG及以上的日志
# 输出格式为 2019-19-06 18:47:06 - WARNING - And this, too
logging.basicConfig(
filename
=
'example.log'
,
filemode
=
'w'
,
level
=
logging.DEBUG,
format
=
'%(asctime)s - %(levelname)s - %(message)s'
,
datefmt
=
'%Y-%d-%d %H:%M:%S'
)
logging.debug(
'This message should go to the log file'
)
logging.info(
'So shoul this'
)
logging.warning(
'And this, too'
)
|
filename日志文件路径 。
filemode记录日志文件的模式,w为每次启动程序都创建一个全新的文件记录, a表示追加到文件末尾, 默认为a 。
level记录日志的等级 。
format日志输出的格式 。
datefmt日志输出时间的格式 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
[loggers]
# 配置日志对象名, 默认为root
keys
=
root, poj
[handlers]
# 日志配置名对象名
keys
=
writeFileHandlers
[formatters]
# 日志输出格式对象名
keys
=
writeFileFormatters
[logger_root]
level
=
DEBUG
handlers
=
writeFileHandlers
[logger_poj]
level
=
DEBUG
handlers
=
writeFileHandlers
qualname
=
writeFileFormatters
propagate
=
0
[logger_leetcode]
level
=
DEBUG
handlers
=
writeFileHandlers
qualname
=
writeFileFormatters
propagate
=
0
[handler_writeFileHandlers]
# 设置writeFileHandlers对象的配置
class
=
FileHandler
level
=
DEBUG
formatter
=
writeFileFormatters
# 记录在文件中,以追加的形式
args
=
(
"demo.log"
,
"a"
)
[formatter_writeFileFormatters]
设置writeFileHandlers对象的输出配置
format
=
%
(asctime)s
-
%
(name)s
-
%
(levelname)s
-
%
(message)s
datefmt
=
%
Y
-
%
d
-
%
m
%
H:
%
M:
%
S
|
1
2
3
4
5
6
7
8
|
import
logging.config
# 加载配置文件
logging.config.fileConfig(
'logging.conf'
)
# 获取日志对象名为poj的
logger
=
logging.getLogger(
"poj"
)
logger.debug(
'This message should go to the log file'
)
logger.info(
'So shoul this'
)
logger.warning(
'And this, too'
)
|
以上为个人经验,希望能给大家一个参考,也希望大家多多支持我。如有错误或未考虑完全的地方,望不吝赐教.
原文链接:https://blog.csdn.net/liuxingen/article/details/44457005 。
最后此篇关于Python 解决logging功能使用过程中遇到的一个问题的文章就讲到这里了,如果你想了解更多关于Python 解决logging功能使用过程中遇到的一个问题的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我正在构建一个 RCP 应用程序,其中每个季度都会更新功能/插件。因此,如果用户选择自动更新功能/插件,则会下载更新插件的新 jar,但旧插件仍在使用我不再使用的磁盘空间。 我厌倦了删除包含旧 jar
我如何从外部 Controller 功能中调用 Controller 内部的功能,例如电话间隙回调功能 这是 Controller 外部定义的功能 function onDeviceReady()
如果某个功能(例如 MediaSource)可用,我如何使用 Google Dart 检查。 new MediaSource() 抛出一个错误。如何以编程方式检查此类或功能是否存在?有任何想法吗?是否
我正在尝试运行 Azure Orchestrations,突然我开始从 statusQueryGetUri 收到错误: 协调器函数“UploadDocumentOrchestrator”失败:函数“U
我见过 iPhone 上的应用程序,如果在 3.0 上运行,将使用 3.0 功能/API,例如应用内电子邮件编辑器,如果在 2.x 上运行,则不使用这些功能,并退出应用程序以启动邮件相反。 这是怎么做
这是 DB 规范化理论中的一个概念: Third normal form is violated when a non-key field is a fact about another non-ke
如果我定义 #if SOMETHING #endif 而且我还没有在任何地方定义 SOMETHING。 #if 中的代码会编译吗? 最佳答案 当#if的参数表达式中使用的名称未定义为宏时(在所有其他宏
我刚刚澄清了 A* 路径查找应该如何在两条路径具有相等值的 [情况] 下运行,无论是在计算期间还是在结束时,如果有两条相等的短路径。 例如,我在我的起始节点,我可以扩展到两个可能的节点,但它们都具有相
Java有没有类似下面的东西 宏 一种遍历所有私有(private)字段的方法 类似于 smalltalk symbols 的东西——即用于快速比较静态字符串的东西? 请注意,我正在尝试为 black
这个程序应该将华氏度转换为摄氏度: #include int main() { float fahrenheit, celsius; int max, min, step;
当打开PC缓存功能后, 软件将采用先进先出的原则排队对示波器采集的每一帧数据, 进行帧缓存。 当发现屏幕中有感兴趣的波形掠过时, 鼠标点击软件的(暂停)按钮, 可以选择回看某一帧的波形
我有一个特殊的(虚拟)函数,我想在沙盒环境中使用它: disable.system.call eval(parse(text = 'model.frame("1 ~ 1")'), envir = e
使用新的 Service 实现,我是否必须为我的所有服务提供一个 Options 方法? 使用我的所有服务当前使用的旧 ServiceBase 方法,OPTIONS 返回 OK,但没有 Access-
我正在阅读 Fogus 的关于 Clojure 的喜悦的书,在并行编程章节中,我看到了一个函数定义,它肯定想说明一些重要的事情,但我不知道是什么。此外,我看不到这个函数有什么用 - 当我执行时,它什么
我有大量的 C 代码,大部分代码被注释掉和/或 #if 0。当我使用 % 键匹配 if-else 的左括号和右括号时,它也匹配注释掉的代码。 有没有办法或vim插件在匹配括号时不考虑注释掉或#if 0
我有这个功能: map(map(fn x =>[x])) [[],[1],[2,3,4]]; 产生: val it = [[],[[1]],[[2],[3],[4]]] 我不明白这个功能是如何工作的。
我使用 Visual Studio 代码创建了一个函数应用程序,然后发布了它。功能应用程序运行良好。我现在在功能门户中使用代码部署功能(KUDU)并跳过构建。下面是日志 9:55:46 AM
我有一个数据框df: userID Score Task_Alpha Task_Beta Task_Charlie Task_Delta 3108 -8.00 Easy Easy
我真的无法解决这个问题: 我有一个返回数据框的函数。但是,数据框仅打印在我的控制台中,尽管我希望将其存储在工作空间中。我怎样才能做到这一点? 样本数据: n <- 32640 t <- seq(3*p
有没有办法找出所有可能的激活器命令行选项? activator -help仅提供最低限度的可用选项/功能列表,但所有好的东西都隐藏起来,即使在 typesafe 网站在线文档中也不可用。 到目前为止,
我是一名优秀的程序员,十分优秀!