如何根据打印时间获取最后一个错误字符串?

时间:2019-05-09 01:43:49

标签: python

我有一个自动更新的日志文件,看起来像这样:

...
[23:32:19.586] PULL START
[23:32:19.637] PULL RESP NONE
[23:32:22.576] Rx - +CMS ERROR: 29
[23:32:22.686] STAT - TRY 2
[23:32:22.797] Tx - AT+CMGF=1
[23:32:23.008] Rx - OK
[23:32:23.017] Tx - at+cmgs="number"
[23:32:23.428] Rx - >
[23:32:23.438] Tx - message
[23:32:24.675] PULL START
[23:32:24.714] PULL RESP NONE
[23:32:26.663] Rx - +CMS ERROR: 29
[23:32:26.681] STAT - 68$$"+CMS ERROR: 29"
[23:32:26.695] SEND - RESPONSE, TRANS ID = xxxxxxxx, RESP CODE = xx, MESSAGE = +CMS ERROR: 29

我有一个要比较的列表,看起来像这样:

[
    '+CMS ERROR: 8',
    '+CMS ERROR: 28',
    '+CMS ERROR: 29',
    '+CMS ERROR: 50',
    '+CMS ERROR: 226',
]

我要做的是,如果日志文件的最后一行具有字符串+CMS ERROR: XX,并且与列表中的一个匹配,我想终止与日志相关的程序。

请注意,只要程序正在运行,日志文件就会一直随机更新,我的程序将每秒钟重新检查一次日志文件。如果更新(日志文件上打印的最后一行)不包含列表中的任何字符串,则不会终止任何程序。

是否可以在python中做到这一点?喜欢使用正则表达式之类的东西?请帮忙。

3 个答案:

答案 0 :(得分:0)

因此,该脚本包含三个主要部分。

  1. 读取并解析日志
  2. 有条件地终止进程
  3. x秒重复一次

第一部分很简单。我们称之为should_act

def should_act():
    errors = ['+CMS ERROR: 8',
        '+CMS ERROR: 28',
        '+CMS ERROR: 29',
        '+CMS ERROR: 50',
        '+CMS ERROR: 226']

    with open("path/to/logfile.log") as f:
        for line in f:
            pass

    return any(error in line for error in errors)

第二部分也不错。我们称之为act

def act():
    pid = YOUR_PROCESS_ID
    subprocess.run(['taskkill', '/PID', str(pid)])
    # or alternatively taskkill /IM YOUR_IMAGE_NAME works too.

第三部分会产生一些问题,但最终也算不错。有很多方法可以做到这一点,最好的方法是在应用程序外部进行调度。 taskschd.msc是在Windows上执行此操作的最佳方法,而cron通常的最佳方法。

在应用程序中执行此操作a bunch of answers,有些比其他更好。我将让您从这些解决方案中进行选择,而建议您使用操作系统安排脚本每x秒运行一次。

import subprocess

# the two code blocks above

if __name__ == "__main__":
    if should_act():
        act()

答案 1 :(得分:0)

您要连续观看文件吗?确实类似于Unix命令tail -f的功能吗?然后,在代码指针之前,我建议选择适合该工作的工具。外包。如果您需要一个进程内解决方案,请查看Watchdog。如果您愿意从子流程中读取内容,请考虑A Windows equivalent of the Unix tail command

中的任何解决方案

同时,如果您绝对必须每次都重新打开文件,请首先寻求结尾以提高效率:

with open('mylog.txt') as logf:
  logf.seek(-1024, 2)    # 2 = magic number to say "from end of file"
  last_line = logf.readlines()[-1]
  for exit_error in exit_error_strings:
    if exit_error in last_line:
      raise SystemExit    # just exit

现在,这假设没有日志行超过1024个字符。如果这不是一个安全的假设,那么显然选择一个安全的值或适当添加其他逻辑。

关于正则表达式,它们通常比您认为的要昂贵(从计算上来说,内存),但是如果进行了测量,您还可以执行以下操作:

import re

exit_error_re = re.compile(r'\+CMS ERROR: \d\d')
...

if exit_error_re.search(last_line):
  # do something

很显然,根据您的需要设置正则表达式。

答案 2 :(得分:-1)

您可以通过将文件转换为数组列表以获取文件的最后一行来执行此操作。您可以将其放入循环中,以便它可以自动更新 我为该示例选择错误编号8

from os import stat

filename = 'log.txt'

statinfo = os.stat(filename)

size = int(str(statinfo.st_size).replace('L', ''))

with open(filename, 'r') as f:
    array_list = fin.seek(size/2) #the will read half of the incase the file size is and you want fast way to read your file
    array_list = array_list.readlines()
    if '+CMS ERROR: 8' in array_list[len(array_list)-1]:
        #Your Code Here