当前位置: 代码迷 >> python >> Python Iterator奇怪地跳过了项目
  详细解决方案

Python Iterator奇怪地跳过了项目

热度:110   发布时间:2023-06-27 21:20:22.0

作为解码通信协议(EDIFACT MSCONS)的程序的一部分,我有一个类,可以给我消息的下一个“段”。 这些段由撇号“'”界定。 可能在“'”之后有换行符。 这是该类的代码:

class SegmentGenerator:
def __init__(self, filename):
    try:
        fh = open(filename)
    except IOError:
        print ("Error: file " + filename + " not found!")
        sys.exit(2)
    lines=[]
    for line in fh:
        line = line.rstrip()
        lines.append(line)
    if len(lines) == 1:
        msg = lines[0]
    else:
        msg = ''
        for line in lines:
            msg = msg + line.rstrip()
    self.segments=msg.split("'")
    self.iterator=iter(self.segments)

def next(self):
    try:
        return next(self.iterator)
    except StopIteration:
        return None

if __name__ == '__main__': #testing only
    sg = SegmentGenerator('MSCONS_21X000000001333E_20X-SUD-STROUM-M_20180807_000026404801.txt')
    for i in range(210436):
        if i > 8940:
            break
    print(sg.next())

为了让您了解文件的外观,以下是该文件的摘录:

UNB+UNOC:3+21X000000001333E:020+20X-SUD-STROUM-M:020+180807:1400+000026404801++TL'UNH+000026404802+MSCONS:D:04B:UN:1.0'BGM+7+000026404802+9'DTM+137:201808071400:203'RFF+AGI:6HYR67925RZUD_000000257860_00_E27'NAD+MS+21X000000001333E::020'NAD+MR+20X-SUD-STROUM-M::020'UNS+D'NAD+DP'LOC+172+LU0000010496200000000000050287886::89'DTM+163:201701010000?+01:303'DTM+164:201702010000?+01:303'LIN+1'PIA+5+1-1?:1.29.0:SRW'QTY+220:9.600'DTM+163:201701010000?+01:303'DTM+164:201701010015?+01:303'QTY+220:10.400'DTM+163:201701010015?+01:303'DTM+164:201701010030?+01:303'QTY+220:10.400'DTM+163:201701010030?+01:303'DTM+164:201701010045?+01:303'QTY+220:10.400'DTM+163:201701010045?+01:303'DTM+164:201701010100?+01:303'QTY+220:10.400'DTM+163:201701010100?+01:303'DTM+164:201701010115?+01:303'QTY+220:10.400'DTM+163:201701010115?+01:303'DTM+164:201701010130?+01:303'QTY+220:10.400'DTM+163:201701010130?+01:303'DTM+164:201701010145?+01:303'QTY+220:10.400'DTM+163:201701010145?+01:303'DTM+164:201701010200?+01:303'QTY+220:11.200'DTM+163:201701010200?+01:303' ...

我有问题的文件有210000个这些段。 我测试了代码,一切正常。 段的列表已完成,我可以正确地得到一个段,然后依次找到另一个段,直到列表末尾。

我将这些段用作状态机的输入,该状态机从SegmentGenerator的实例获取新的段。

摘录如下:

    def DTMstarttransition(self,segment):
    match=re.search('DTM\+(.*?):(.*?):(.*?)($|\+.*|:.*)',segment)
    if match:
        if match.group(1) == '164':
            self.currentendtime=self.dateConvert(match.group(2),match.group(3))
            return('DTMend',self.sg.next())
    return('Error',segment + "\nExpected DTM segment didn't match")

该方法返回下一个状态和下一个段的名称sg.next(),其中sg是SegmentGenerator的实例。

但是,在8942st段上,调用sg.next()不会给我下一个段,而是给我第二个段列表!

我跟踪了功能调用(使用自动记录模块):

TRACE:segmentgenerator.SegmentGenerator:next:CALL *() **{}
TRACE:segmentgenerator.SegmentGenerator:next:RETURN 'DTM+164:201702010000?+01:303'
TRACE:__main__.MSCONSparser:QTYtransition:RETURN ('DTMstart', 'DTM+164:201702010000?+01:303')
TRACE:__main__.MSCONSparser:DTMstarttransition:CALL *('DTM+164:201702010000?+01:303',) **{}
TRACE:__main__.MSCONSparser:dateConvert:CALL *('201702010000?+01', '303') **{}
TRACE:__main__.MSCONSparser:dateConvert:RETURN datetime.datetime(2017, 2, 1, 0, 0)
TRACE:segmentgenerator.SegmentGenerator:next:CALL *() **{}
TRACE:segmentgenerator.SegmentGenerator:next:RETURN 'UNT+17872+000026404802'
TRACE:__main__.MSCONSparser:DTMstarttransition:RETURN ('DTMend', 'UNT+17872+000026404802')
TRACE:__main__.MSCONSparser:DTMendtransition:CALL *('UNT+17872+000026404802',) **{}

UNT + ...不是下一个段,它应该是LIN段。 但这怎么可能呢? 为什么我在其模块中的main函数对其进行测试时,SegmentGenerator可以工作,而在另一个模块进行数千次调用后却无法正常工作?

所有段都从头到尾都在那里。 我可以从解释器验证这一点,因为程序停止后,列表sg.segments仍然可用。 len(sg.segments)是210435,但是我的程序在8942之后停止。因此,显然迭代器存在问题。

如果您想测试整个文件,可以在的“ next”分支中找到文件(3个python文件和数据示例)。

我认为您的数据文件中第8942个撇号附近可能存在双撇号''。

在这种情况下,您的代码将继续读取整个文件,并读取所有210435段。

但是,如果您有条件测试sg.next()的结果,那么在第8942次迭代中这将是错误的,而且我猜测这会导致您的程序中止。

例如:

while sg.next():
   # some processing here

如果我完全错了,那么我会对观察这种行为感兴趣:-len和迭代应该相等。

if __name__ == '__main__':
    fn = sys.argv[1]
    sg = SegmentGenerator(fn)

    print("Num segments:", len(sg.segments))
    i = 0
    value = 'x'
    while value:
        value = sg.next()
        i += 1
        print(i, value)

    print("Num iterations:", i)

事实证明,文件'DTM + 164:201702010000?+01:303'中第二次出现了该文件,并且确实存在一个UTM段。 因此问题出在协议状态本身,并且迭代器正常工作。 非常抱歉,我以错误的假设打扰了您。 感谢您的帮助!

  相关解决方案