在尝试使用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()
答案 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)