【问题标题】:Python recursively execute try except while condition is fulfilledPython递归执行try,除非条件满足
【发布时间】:2019-08-25 12:46:34
【问题描述】:

我想逐行迭代文本文件并搜索模式并从中提取实体。但是,提取的几个模式具有多行特征,当我逐行迭代时会丢失这些特征。

现在,我正在使用 try-except 块并将下一行附加到当前行,例如:

try:
    id_value, utterance, prediction = process(line + ' ' + lines[n + 1])
except AttributeError:
    # Handle bad data
    try:
        id_value, utterance, prediction = process(line + ' ' + lines[n + 1] + ' ' + lines[n + 2])
    except AttributeError:
        # Handle bad data
        try:
            id_value, utterance, prediction = process(
                line + ' ' + lines[n + 1] + ' ' + lines[n + 2] + ' ' + lines[n + 3])

这是数据:

数据.txt

[22 Aug 2019 13:25:12] [ID:9ea1566460506294]     INFO [139921763325696] (ModelClassification:056) - Model classification for utterance_1 is 1
[22 Aug 2019 13:26:06] [ID:7ea1566460117776]     INFO [139921771718400] (ModelClassification:056) - Model classification for  utterance_2
 is 1
[22 Aug 2019 13:26:16] [ID:71d1566460492762]     INFO [139921771718400] (ModelClassification:056) - Model classification for utterance_3 is 0 

如你所见

[22 Aug 2019 13:26:06] [ID:7ea1566460117776]     INFO [139921771718400] (ModelClassification:056) - Model classification for  utterance_2
 is 1

在逐行迭代时扩展 2 行。

代码

import re

matching_string = 'Model classification for'
id_start_string = '[ID:'
id_end_string = ']'


def process(line):
    start_idx = line.find(id_start_string)
    end_idx = [s.start() for s in re.finditer(id_end_string, line)]
    for end in end_idx:
        if end > start_idx:
            # Get first index greater than start string index
            end_idx = end
            break
    id_value = line[start_idx + len(id_start_string): end_idx]
    groups = re.search('Model classification for (.*) is (0|1)', line).groups()
    utterance = groups[0]
    prediction = groups[1]
    return id_value, utterance, prediction


with open('data.txt', 'r') as f:
    lines = f.read().splitlines()
    for n, line in enumerate(lines):
        # Search for pattern in string
        if matching_string in line:
            try:
                id_value, utterance, prediction = process(line)
            except AttributeError:
                 print('Bad data')
                 print(line)
            print(id_value, utterance, prediction)

我的问题可以有递归解决方案吗?非常感谢任何帮助。

编辑 -

lines = ['22 Aug 2019 13:25:12] [ID:9ea1566460506294]     INFO [139921763325696] (ModelClassification:056) - Model classification for utterance_1 is 1', '[22 Aug 2019 13:26:06] [ID:7ea1566460117776]     INFO [139921771718400] (ModelClassification:056) - Model classification for  utterance_2', ' is 1', '[22 Aug 2019 13:26:16] [ID:71d1566460492762]     INFO [139921771718400] (ModelClassification:056) - Model classification for utterance_3 is 0 ']

【问题讨论】:

  • 您能否扩展您的代码,使其不依赖于未指定的data.txt 文件?只需对字符串数组进行硬编码,这就是您在lines 中得到的内容,希望不会导致问题(请验证!)。
  • 编辑了我的问题。 data.txt 已指定。
  • 不,不要添加编辑部分。提取并提供minimal reproducible example 应该是您的目标。

标签: python list csv text


【解决方案1】:

如果你想在文件中查找一行。您可以为此使用 re.findall()

import re
with open("input.txt", "r") as f:
    text = f.read()

output = re.findall(r'some regex pattern', text)
output1 = re.findall(r'some other pattern', text)
output2 = re.findall(r'another pattern', text)

with open("output.txt", "w") as f:
    f.write(output)
    f.write(output1)
    f.write(output2)

如果你想递归地做,你可以,但 re.findall 听起来像你需要的。

【讨论】:

    【解决方案2】:

    要回答最初的问题(并且不考虑 process 的实际作用),请逐步迭代更大的组合:

    value = line
    for extra in lines[n+1:]:
        value = value + " " + extra
        try:
            id_value, utterance, prediction = process(value)
            break
        except AttributeError:
            pass
    

    【讨论】:

      【解决方案3】:

      如果您只想使用换行符进行捕获,您可以修改您的正则表达式以接受可能的换行符(空白)字符:

      r'Model classification for (.*)\s? is (0|1)'
      

      使用 re.findall 在整个文件上运行它

      【讨论】:

      • 这行不通,因为延续部分在下一次迭代中。
      • 对不起,不要在每一行都运行正则表达式。使用 re.findall 在整个文件上运行它。然后你就可以遍历匹配了。
      【解决方案4】:

      我将为这个问题编写自己的解决方案。我在我的应用程序中遇到了类似的事情。 作为输入,您的示例日志将被使用。

      假设我们有一个包含日志的文件(我稍微复杂了一点):

      [22 Aug 2019 13:25:12] [ID:9ea1566460506294]     INFO [139921763325696] 
      (ModelClassification:056) - Mod
      el classification for utterance_1 is 1
      [22 Aug 2019 13:26:06] [ID:7ea1566460117776]     INFO [13992177
      1718400] (ModelClassification:056) - Model classificat
      ion for  utterance_2
       is 1
      [22 Aug 2019 13:26:16] [ID:71d1566460492762]     INFO [139921771718400] (ModelC
      lassification:056) - Model classification for utterance_3 is 0
      

      现在,我的目标是收集单个日志。单个日志是从数据开始并以另一行结束,该行从下一个数据开始。 (该文件包含很多单个日志) 当我正确解析单个日志时,我可以找到正则表达式。

      代码:

      import re
      
      START_LINE_REGEX = re.compile(r'^\[\d+')
      MAIN_MATCHER = re.compile(r'(\[ID:\w+\]).* Model classification for (.*) is (0|1)')
      
      def read_file(file_path):
          """
          Read file from path, and return iterator.
          """
          with open(file_path, 'r') as f:
              return iter(f.read().splitlines())
      
      def verify_line(line):
          """
          Check if line starts with proper regex. 
          """
          return True if START_LINE_REGEX.match(line) else False
      
      def single_log(iterator):
          """
          Generator, parse log.
          """
          content = [next(iterator)]
          for line in iterator:
              state = verify_line(line)
              if state:
                  yield "".join(content)
                  content = [line]
              else:
                  content.append(line)
          yield "".join(content)
      
      def get_patterns(log):
          """
          Read values from given regex and a one, big line ( a single log )
          """
          matcher = MAIN_MATCHER.search(log)
          if matcher:
              return matcher.group(1), matcher.group(2), matcher.group(3)
          else:
              print("Could not get groups from '{}'".format(log))
      
      
      if __name__ == '__main__':
          iterator = read_file('stackoverflow.log')
      
          gen = single_log(iterator)
          for index, log in enumerate(gen):
              print("{}: {}".format(index, log))
              print("Found regexes: {}".format(get_patterns(log)))
      

      结果:

      0: [22 Aug 2019 13:25:12] [ID:9ea1566460506294]     INFO [139921763325696] 
      (ModelClassification:056) - Model classification for utterance_1 is 1
      Found regexes: ('[ID:9ea1566460506294]', 'utterance_1', '1')
      1: [22 Aug 2019 13:26:06] [ID:7ea1566460117776]     INFO [139921771718400]         
      (ModelClassification:056) - Model classification for  utterance_2 is 1
      Found regexes: ('[ID:7ea1566460117776]', ' utterance_2', '1')
      2: [22 Aug 2019 13:26:16] [ID:71d1566460492762]     INFO [139921771718400]         
      (ModelClassification:056) - Model classification for utterance_3 is 0
      Found regexes: ('[ID:71d1566460492762]', 'utterance_3', '0')
      

      这取决于启动日志格式,但如果你改进正则表达式,我相信它会比在列表中使用索引更有价值。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-05-31
        • 2017-09-16
        • 2021-06-06
        • 2017-10-26
        • 1970-01-01
        • 2021-09-05
        相关资源
        最近更新 更多