尝试使用pyparsing解析重复字符时出错

时间:2016-01-23 15:50:33

标签: python-3.x pyparsing

在尝试使用pyparsing解析某些文本时,我遇到了意外行为。我正在逐行解析一些半结构化文本,其中一条可能的行是一个记录分隔符,它包含整行'='字符,如下所示:

“============================================== ===='

此时也可能有一个空行,所以我必须尝试这两个选项。如果我尝试使用以下定义解析仅包含空格的行(假定为import pyparsing as pp):pp.Word('=', min=10),则会出现IndexError: string index out of range错误而不是预期的pyparsing异常-比赛。定义pp.OneOrMore(pp.Word('='))具有预期的行为,因此我当然会在我的代码中使用它。我的理解是这些定义在这种情况下应该是等价的,并且pyparsing应该返回ParseException而不是IndexError。我错过了什么吗?

import unittest
import pyparsing as pp


class Test(unittest.TestCase):


    def testSepDetail(self):
        verbose = True
        pattern1 = pp.Word('=', min=10) # Throws IndexError: string index out of range
        pattern2 = pp.OneOrMore(pp.Word('=')) # Works as expected
        testPattern = pattern1
        testList = [
('=======================','======================='),
('     ',None)]
        for test in testList:
            text, expected = test
            result = self.harness2(testPattern, text, expected, verbose)

    def harness2(self,pattern, text, expected, verbose):
        '''
        '''

        if verbose:
            print('\n---Test for: {0}'.format(text))
        try:
            result = pattern.parseString(text)
            if verbose:
                print('Parse successful.\n', result.dump())
            if expected:
                self.assertEqual(expected, result[0], "\n\tParse Successful, but data not as expected.\n\tExpected {0}\n\t but got {1}".format(expected, result[0]))
            return result          
        except pp.ParseException as x:
            failmsg = "\n---Failed to parse string: {0}\n{1}".format(text,str(x))
            print(failmsg)
            self.fail(failmsg)


if __name__ == "__main__":
    #import sys;sys.argv = ['', 'Test.testName']
    unittest.main()

1 个答案:

答案 0 :(得分:0)

这不是你的错误,它是pyparsing中的一个错误,是在忘记以前以冲突的方式优化代码后重新优化代码的结果。这个问题实际上影响了几个pyparsing类,而不仅仅是Word(主要是那些来自pyparsing'令牌类的子类)。

实际上这不是一个问题,因为Token类型的表达式很少被孤立地使用,而容器表达式(如OneOrMore等)都会陷入IndexError并重新引发ParseException。

例如,这些也可以解决Word中的IndexError问题:

pattern2 = pp.empty + pp.Word('=')
pattern2 = 1*pp.Word('=')

我肯定会在下一个版本中对此进行清理,但在您的应用程序中,我认为如果您将处理程序更改为:

except (pp.ParseException, IndexError) as x:

然后,当您升级到固定版本时,您只需要更改一个except语句,而不是您使用OneOrMore攻击的语法中的所有位置。

注意:如果您将self.fail调用更改为:

,您还可以让测试平台容忍异常情况
        if expected is not None:
            self.fail(failmsg)