Python日志截取脚本问题:起始行正确但结束行定位错误求助
问题分析与修复方案
你的脚本出现结束行定位错误的核心原因是文件对象的迭代器特性:当你第一次使用enumerate(file)遍历查找起始行时,文件指针会移动到起始行的下一行位置;第二次再调用enumerate(file)时,会从当前指针位置继续遍历,而且行号是从1重新开始计数的,这就导致你得到的end_line_number是相对于当前指针位置的行号,而不是整个文件中的实际行号。
修复方法1:重置文件指针后重新遍历
在找到起始行号后,将文件指针重置到文件开头,再重新遍历查找结束行号,这样就能得到正确的全局行号:
import optparse import datetime parser = optparse.OptionParser() parser.add_option("-f","--file",dest="log_file", action="store",help="Specify log file to be parsed") options, args = parser.parse_args() vLogFile=options.log_file start_time = raw_input("Please enter start time:\n[Format: HH:MM]=") end_time = raw_input("Please enter end time:\n[Format: HH:MM]=") trim_time = datetime.datetime.now().strftime('%d%H%M%S') output_file = 'trimmed_log_%s.txt' %trim_time with open(vLogFile) as file: # 获取日志的日期部分 for vline in file: vDate = vline[0:10] break start_line = vDate + ' ' + start_time end_line = vDate + ' ' +end_time print("Start time:%s" %start_line) print("End time:%s" %end_line) # 重置指针到开头,因为刚才获取日期时已经移动了指针 file.seek(0) # 查找起始行号 start_line_number = None for num, line in enumerate(file, 1): if line.startswith(start_line): start_line_number = num break # 重置指针到开头,查找结束行号 file.seek(0) end_line_number = None for num, line in enumerate(file, 1): if line.startswith(end_line): end_line_number = num break print(start_line_number,end_line_number) with open(vLogFile,"r") as file: oFile = open(output_file,'a') for num, line in enumerate(file, 1): if num >= start_line_number and num <= end_line_number: oFile.write(line) print("%s Created" %output_file)
注意这里额外添加了一次指针重置:获取日期后指针已经移动到第二行,重置后才能确保起始行的查找是从文件开头开始的。
修复方法2:一次遍历完成行号定位(更高效)
我们可以只遍历一次文件,同时记录起始和结束行号,避免多次重置指针和重复遍历,对大日志文件更友好:
import optparse import datetime parser = optparse.OptionParser() parser.add_option("-f","--file",dest="log_file", action="store",help="Specify log file to be parsed") options, args = parser.parse_args() vLogFile=options.log_file start_time = raw_input("Please enter start time:\n[Format: HH:MM]=") end_time = raw_input("Please enter end time:\n[Format: HH:MM]=") trim_time = datetime.datetime.now().strftime('%d%H%M%S') output_file = 'trimmed_log_%s.txt' %trim_time start_line_number = None end_line_number = None vDate = None with open(vLogFile) as file: # 一次遍历完成日期获取、起始和结束行号定位 for num, line in enumerate(file, 1): if not vDate: vDate = line[0:10] start_line = vDate + ' ' + start_time end_line = vDate + ' ' + end_time print("Start time:%s" %start_line) print("End time:%s" %end_line) if line.startswith(start_line) and start_line_number is None: start_line_number = num if line.startswith(end_line): end_line_number = num print(start_line_number,end_line_number) with open(vLogFile,"r") as file: oFile = open(output_file,'a') for num, line in enumerate(file, 1): if start_line_number <= num <= end_line_number: oFile.write(line) print("%s Created" %output_file)
额外优化建议
- 添加异常判断:如果
start_line_number或end_line_number为None(未找到对应时间的日志行),给出明确提示,避免后续代码报错。 - 对用户输入的时间做格式校验,确保符合
HH:MM的要求,提升脚本健壮性。
内容的提问来源于stack exchange,提问作者pgyogesh
相关产品推荐
相关产品推荐

