Python迭代器奇怪地跳过了项

2024-06-02 08:43:16 发布

您现在位置:Python中文网/ 问答频道 /正文

作为对通信协议(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个这样的段。我测试了代码,一切正常。段的列表是完整的,我得到了一个又一个正确的段,直到列表结束。你知道吗

我使用这些段作为statemachine的输入,statemachine从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.下一个(),sg是SegmentGenerator的实例。你知道吗

但是在第8942段sg.下一个()不会给我下一个片段,而是片段列表的最后一个!你知道吗

我跟踪了函数调用(使用autologging模块):

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段。 但这怎么可能呢?为什么SegmentGenerator在我用它的模块中的main函数测试它时能工作,而在从另一个模块调用了数千次之后却不能正常工作?你知道吗

所有的片段从头到尾都在那里。我可以从口译员那里核实,因为sg段程序停止后保持可用。伦(sg段)是210435,但我的程序在8942后停止。所以这显然是迭代器的问题。你知道吗

这些文件(3个python文件和数据示例)可以在分支“next”的Github上找到,如果您想测试整个过程的话。你知道吗


Tags: selfifmainmatchlinetracemsgcall
2条回答

结果是一段'DTM+164:201702010000?+01:303'在文件的更深处第二次存在,而且确实是一个UTM段。所以问题在于协议状态本身和迭代器工作正常。 很抱歉,我的错误假设打扰了你。谢谢你的帮助!你知道吗

我认为在你的数据文件中有可能有一个双撇号',在第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)

相关问题 更多 >