从日志文件提取新错误并发送邮件结果
下面这个Python 2.5的脚本可以正常工作,但因为我还是个初学者,所以想知道有没有明显的错误,或者有没有更好的方法来实现我想做的事情。
我的目标是打开今天的日志文件,路径是'/Library/Application Support/Perceptive Automation/Indigo 5/Logs/',然后提取出包含“error”这个词的行,并且只发送新的错误信息到邮箱。提取出错误行后,会先计算一下这些行的数量(prenumLines
),然后把提取的行写入到tmp.txt
文件中,再次计算行数(postnumLines
)。最后,行号大于prenumLines
的行会被打印到'theBody'中,并发送邮件。
from datetime import date
import linecache
fileDate = str(date.today())
theBody = []
tmpFile = open('/Library/Application Support/Perceptive Automation/Indigo 5/Logs/tmp.txt')
prenumLines = sum(1 for line in tmpFile)
log= open( '/Library/Application Support/Perceptive Automation/Indigo 5/Logs/' + fileDate + ' Events.txt', 'r' )
tmpFile = open('/Library/Application Support/Perceptive Automation/Indigo 5/Logs/tmp.txt', 'w')
for line in log:
if 'Error' in line:
tmpFile.write(line )
log.close()
tmpFile.close()
postnumLines = sum(1 for line in open('/Library/Application Support/Perceptive Automation/Indigo 5/Logs/tmp.txt'))
lineNum = prenumLines
while lineNum < postnumLines:
theBody.append(linecache.getline( '/Library/Application Support/Perceptive Automation/Indigo 5/Logs/tmp.txt', lineNum + 1) )
lineNum = lineNum + 1
tmpFile.close()
theBody = "".join(theBody)
#theBody is the body of an email which is sent next
#print theBody
2 个回答
Anthon,非常感谢你抽出时间回复我。生成日志的软件是Perceptive Automation Indigo,这是一款家居自动化程序。它会不断地写入日志,每天生成一个新的日志。我设置了一个Python脚本,每10分钟解析一次日志,查找错误,然后把错误通过邮件发给我。我的挑战是只发送新的错误,避免重复发送之前已经发过的错误。我是通过计算tmp.txt文件中的行数来实现的,然后再添加新的错误。如果之前有错误写入过,那些错误会被覆盖。所以,如果tmp.txt里有5行,新增3行的话,邮件里只会发给我这3行新的内容。我也做了一些你建议的改动,比如使用了with语句,这样简化了脚本,省去了关闭文件的步骤。我还把文件名替换成了变量。做完这些后,脚本运行得很好,但由于软件设计的原因,我不能使用包含'with语句'的脚本。现在我得重新写这个脚本,去掉with语句。你帮了我很多,非常感谢你。
根据我的经验,有些改动你真的应该考虑做一下(我用必须这个词,但其实只是个建议),还有一些是我个人的风格(我用应该)。
从整体来看:你最开始的问题只标记了python-25,这可能是它没有引起关注的原因,你必须使用python,因为这个标签在StackOverflow上有很多粉丝。
你必须在文件中不要同时使用TAB和空格字符。因为这个原因,你在SO上的代码缩进实际上是错误的。那行代码:tmpFile.write(line)
应该缩进到上面if
语句的下一层。
你必须不要四次使用同一个字符串作为文件名,而是用一个变量来替代它。并且用os.path.join()
从公共基础目录创建这个变量。
你应该考虑遵循PEP8,这是Python的风格指南。
如果你第一次尝试这个程序,它是不会运行的,因为'tmp.txt'并不存在。优雅地处理这个问题,设置prenumLines为0(不过我现在根本不再使用这个,见下面):
try:
# open the file
# count the lines
except:
prenumLines = 0
我其实很奇怪你说你的代码能运行,因为你覆盖了tmp.txt
,并且只把最后一条日志中的错误行写进去了。当你再次给tmpFile
赋值时,第一次打开的读取就关闭了。你接着又关闭了为写入打开的tmpFile
两次(Python对此不会报错)。如果昨天的日志有一个错误,今天有三个,你的邮件只会显示两行。要向文件追加内容,使用open(filename, 'a')
你应该考虑在读写文件时使用with语句(在Python 2.5中新增),这样可以避免(错误的.close()
语句)。
你应该考虑把theBody
作为一个字符串来创建,并逐行添加内容。虽然先用列表再连接可能更快,但这个脚本一天只运行一次。
没有必要先计算行数,然后再追加错误行,最后再重新读取并存储到theBody
中,你应该省去第一和第三部分,一次性完成所有操作:
from __future__ import with_statement
import os
from datetime import date
baseDir = '/Library/Application Support/Perceptive Automation/Indigo 5/Logs'
tmpFileName = os.path.join(baseDir, 'tmp.txt')
fileDate = str(date.today())
eventFileName = os.path.join(baseDir, fileDate + ' Events.txt')
theBody = ''
with open(tmpFileName, 'a') as tmpFile:
with open( eventFileName, 'r' ) as log:
for line in log:
if 'Error' in line:
tmpFile.write(line)
theBody += line
# theBody is the body of an email which is sent next
print theBody