从日志文件提取新错误并发送邮件结果

0 投票
2 回答
1669 浏览
提问于 2025-04-17 17:37

下面这个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 个回答

0

Anthon,非常感谢你抽出时间回复我。生成日志的软件是Perceptive Automation Indigo,这是一款家居自动化程序。它会不断地写入日志,每天生成一个新的日志。我设置了一个Python脚本,每10分钟解析一次日志,查找错误,然后把错误通过邮件发给我。我的挑战是只发送新的错误,避免重复发送之前已经发过的错误。我是通过计算tmp.txt文件中的行数来实现的,然后再添加新的错误。如果之前有错误写入过,那些错误会被覆盖。所以,如果tmp.txt里有5行,新增3行的话,邮件里只会发给我这3行新的内容。我也做了一些你建议的改动,比如使用了with语句,这样简化了脚本,省去了关闭文件的步骤。我还把文件名替换成了变量。做完这些后,脚本运行得很好,但由于软件设计的原因,我不能使用包含'with语句'的脚本。现在我得重新写这个脚本,去掉with语句。你帮了我很多,非常感谢你。

0

根据我的经验,有些改动你真的应该考虑做一下(我用必须这个词,但其实只是个建议),还有一些是我个人的风格(我用应该)。

从整体来看:你最开始的问题只标记了,这可能是它没有引起关注的原因,你必须使用,因为这个标签在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

撰写回答