Python在文件中获取行号

时间:2017-06-14 07:08:52

标签: python file parsing line-numbers

我构建了一个python(2.7)脚本,用这段代码解析txt文件:

cnt = 1

logFile = open( logFilePath, 'r' )

for line in logFile:
    if errorCodeGetHostName in line:
        errorHostNameCnt = errorHostNameCnt + 1
        errorGenericCnt = errorGenericCnt + 1
        reportFile.write( "--- Error: GET HOST BY NAME @ line " + str( cnt ) + "\n\r" )
        reportFile.write( line )


    elif errorCodeSocke462 in line:
        errorSocket462Cnt = errorSocket462Cnt + 1
        errorGenericCnt = errorGenericCnt + 1
        reportFile.write("--- Error: SOCKET -462 @ line " + str(cnt) + "\n\r" )
        reportFile.write(line)


    elif errorCodeMemory in line:
        errorMemoryCnt = errorMemoryCnt + 1
        errorGenericCnt = errorGenericCnt + 1
        reportFile.write("--- Error: MEMORY NOT RELEASED @ line " + str(cnt) + "\n\r" )
        reportFile.write(line)

    cnt = cnt + 1

我想添加每个错误的行号,为此我添加了一个计数器(cnt),但其值与实际行号无关。

这是我的日志文件:

=~=~=~=~=~=~=~=~=~=~=~= PuTTY log 2017.06.13 17:05:43 =~=~=~=~=~=~=~=~=~=~=~=
UTC Time fetched from server #1: '0.pool.ntp.org'


   *** Test (cycle #1) starting...
   --- Test01 completed successfully!
   --- Test02 completed successfully!
   --- Test03 completed successfully!
   --- Test04 completed successfully!
   --- Test01 completed successfully!
   --- Test02 completed successfully!
INF:[CONFIGURATION] Completed
   --- Test03 completed successfully!
Firmware Version: 0.0.0


   *** Test (cycle #1) starting...

如何获得真实的行号?

感谢您的帮助。

2 个答案:

答案 0 :(得分:1)

除了行结尾问题之外,此代码还存在一些其他问题

文件句柄

如评论中所述,最好打开带有with语句的文件

功能分离

现在你有一个大循环,你可以循环遍历原始文件,解析它并立即写入ReportFile。我认为最好将它们分开。

使一个函数循环遍历日志,返回所需的详细信息,以及循环显示这些详细信息并将其写入报告的下一个函数。这是一个更强大,更容易调试和测试出错的时候

我也会让IO尽可能多地在外面。如果您以后想要流式传输到套接字或其他东西,这可以轻松完成

DRY

代码的第6到第24行包含很多几乎相同的行,如果要添加另一个要报告的错误,则需要添加另外5行代码,几乎相同。我会使用dict和for循环来剪切样板代码

Python化

较小的一点是,您不会使用Python提供的方便的内容,例如yield with - 语句,enumeratecollections.counter也可变命名不符合PEP-8,但主要是审美

我的尝试

errors = {
    error_hostname_count: {'error_msg' = '--- Error: GET HOST BY NAME @ line %i'},
    error_socker_462: {'error_msg' = '--- Error: SOCKET -462 @ line %i'},
    error_hostname_count: {'error_msg' = '--- Error: MEMORY NOT RELEASED @ line %i'},
    }

在此定义可能发生的错误以及错误消息的外观

def get_events(log_filehandle):
    for line_no, line in enumerate(log_filehandle):
        for error_code, error in errors.items():
            if error_code in line:
                yield line_no, error_code, line

这只需要一个文件句柄(也可以是一个流或缓冲区),只是在那里查找error_codes,如果找到一个,它就会与行一起产生

def generate_report(report_filehandle, error_list):
    error_counter = collections.Counter()
    for line_no, error_code, error_line in error_list:
        error_counter['generic'] += 1
        error_counter[error_code] += 1

        error_msg = format_error_msg(line_no, error_code)
        report_file.write(error_msg)
        report_file.write(error_line)
    return error_counter

这会循环找到找到的错误。它会增加它们的计数器,格式化消息并将其写入report_file

def format_error_msg(line_no, error_code):
    return errors[error_code['error_msg'] % line_no

这使用字符串格式从error_code和line_no

生成消息
with open(log_filename, 'r') as log_filehandle, open(report_filename, 'w') as report_filehandle:
    error_list = get_events(log_filehandle):
    error_counter = print_events(report_filehandle, error_list)

这将它们联系在一起。您可以使用error_counter向报告添加摘要,或将摘要写入另一个文件或数据库。

这种方法的优点是,如果您的错误识别发生变化,您可以独立于报告执行此操作,反之亦然

答案 1 :(得分:0)

简介:我想要解析的日志来自用C语言编写的嵌入式平台。

我在嵌入式代码中发现,某处有一个带 \ n \ r 的printf而不是 \ r \ n 。我将每个 \ n \ r 替换为与 CR LF 对应的 \ r \ n

通过此更改,python脚本可以正常工作!我可以通过它来确定错误。