我有一个运行几个python进程的红帽企业linux系统。每个进程通过标准pythonWatchedFileHandler
写入同一个日志文件。他们一起每秒写几十个条目。平均条目长度大约为200字节,有时更长。
我想我应该把那个文件中的条目弄混了。但我好像什么也没找到。为什么?操作系统能保证低于阈值长度的数据吗?我可以找到管道和fifo中提到的(PIPE_BUF
),但不是常规文件。或者比赛条件对我在一个典型系统上的负荷来说太窄了?
最佳答案
从文档中:
http://docs.python.org/2.7/library/logging.handlers.html#watchedfilehandler
watchedFileHandler类,位于logging.handlers模块中,
是一个文件处理程序,它监视它正在登录到的文件。如果文件
更改后,它将关闭并使用文件名重新打开。
watchedfilehandler在linux上工作,但在windows上不工作(因为它没有inode)。它监视文件inode上的更改。如果该文件上有任何更改,则该文件将被关闭并再次打开。
根据watchedfilehandler是如何实现的,我认为它们会重复这个过程,直到它可以安全地写入文件为止,但这可能意味着您的进程在不断地打开/关闭日志文件。
更正:它尝试关闭一次,然后再次重新打开文件。我在寻找另一种解释,解释你为什么对它没有问题。
到目前为止,我还没有找到任何理由来解释为什么你的日志中没有混合行。watchedfilehandler被设计为供一个应用程序使用(在发出之前使用rlock控制多线程访问,有一个有价值的异常支持外部更改,如日志旋转)。但在查看其超级类的源代码时,我没有找到任何原因。一个未经检验的理论是:
a)因为日志总是以追加模式打开
b)在写之前,如果有任何变化,它会检查一次
c)您总是得到一个完整的行,因为您的行小于写缓冲区。所以你从最后一行的末尾开始,写一个新行,这个过程一次又一次地重复。如果两个进程同时写入,它们将从最后一行的末尾开始写入新行。
试着在日志行上寻找异常,比如丢失的行…如果日志的大小非常规则,则很难检查并发问题。我也会在日志的最后一行寻找异常。
你的系统有多少处理器?
中断日志的测试程序:
import logging
import logging.handlers
import sys
FORMAT = "%(asctime)-15s %(process)5d %(message)s"
logger = logging.getLogger(__name__)
wfh = logging.handlers.WatchedFileHandler("test.log", "a")
wfh.setFormatter(logging.Formatter(FORMAT))
logger.addHandler(wfh)
logger.setLevel(logging.DEBUG)
n = int(sys.argv[1])
for x in range(1000):
logger.info("%6d %s" % (x, str(n)*(4096+n)))
使用简单的shell脚本运行:
python test.py 1 &
python test.py 2 &
python test.py 3 &
python test.py 4 &
python test.py 5 &
python test.py 6 &
python test.py 7 &
python test.py 8 &
python test.py 9 &
运行在带有4个处理器的CentOS 6.3上,我开始看到线路上的异常。您可以在程序中更改行的大小,小行看起来可以,但大行不行。
您可以使用:
grep -v ^2013 test.log
如果日志正常,所有行将从2013开始。grep不会列出混合行,但我可以用更少的代码轻松找到它们。
因此,它对您有效,因为您的行比您的写缓冲区小,或者因为您的进程不经常写入日志,但即使是它们,也不能保证它一直有效。
关于python - 为什么在并行写入文件时看不到交错的行?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/20634195/