队列数据的for循环迭代问题

0 投票
3 回答
681 浏览
提问于 2025-04-15 17:35

我在从服务器读取和处理数据时遇到了问题。我花了好几个小时来调试,似乎问题和服务器没有关系,而是我一个循环的代码出了问题。没有看到服务器的数据,很难解释清楚,但我会尽量说明。

简单来说,我有一个服务器,当我发送一个命令时,它会依次返回5个不同的XML字符串。我的程序会把这些数据解析成Python字典,并存储在不同的类属性中。因为TCP是一个流,我通常不会单独收到每个字符串。通常的情况是,我会先收到第一个字符串,然后接下来的4个字符串会成对到达。所以,循环通常会执行3次。然而,最后一个字符串却没有被处理和存储到属性中。以下是包含那个循环的逻辑:

 def xmlParser(self, newData):
     print newData
     for string in newData:
         if 'a' in string:
             print 'string1 being processed'
             xmlToDictionary(string, 'string1')
         elif 'b' in string:
             print 'string2 being processed'
             xmlToDictionary(string, 'string2')
         elif 'c' in string:
             print 'string3 being processed'
             xmlToDictionary(string, 'string3')
         elif 'd' in string:
             print 'string4 being processed'
             xmlToDictionary(string, 'string4')
         elif 'e' in string:
             print 'string5 being processed'
             xmlToDictionary(string, 'string5')

这些打印语句只是为了调试用。我第一次发现最后一个字符串没有被处理时,觉得可能是根本没有收到它。不过,通过打印newData,我可以确认所有字符串都收到了,并且都传递给了这个函数。newData是一个包含待处理字符串的列表。在3次不同的循环中,newData看起来是这样的:

newData = ['string1']
newData = ['string2', 'string3']
newData = ['string4', 'string5']

没有被处理的是'string5',我觉得这不是因为在xmlToDictionary()中抛出了异常,因为没有打印出“正在处理字符串5”。而且如果我在函数中加一个else语句,它也没有被执行。就好像这个循环在处理最后一组数据时,拒绝进行第二次迭代。为了进一步测试,我修改了服务器脚本,让'string5'在'string4'之前发送,结果让我惊讶的是,这完全解决了问题,'string5'被成功处理并存储为字典。在这种情况下,newData看起来是这样的:

newData = ['string1']
newData = ['string2', 'string3', 'string5']
newData = ['string4']

我还尝试修改服务器脚本,完全不发送'string4'。这也成功地让'string5'得以处理。这个循环只执行了两次,newData看起来是这样的:

newData = ['string1']
newData = ['string2', 'string3', 'string5']

我试着把这些信息整理在一起,想弄清楚问题出在哪里,但我完全搞糊涂了。我从来没有遇到过这样的情况。如果我找不到解决办法,我要么就让脚本在'string4'之前发送'string5',要么就把所有字符串合并在服务器上,作为一个大字符串发送。不管怎样,我还是想弄清楚这里发生了什么,因为这可能表明我的程序存在更深层次的问题。

3 个回答

1

我刚刚试了你的代码,结果如下:

def xmlParser(newData):
     for string in newData:
         print string
         if 'a' in string:
             print 'string1 being processed'
         elif 'b' in string:
             print 'string2 being processed'
         # ...
         elif 'e' in string:
             print 'string5 being processed'

newData = ['string1']
xmlParser(newData)
newData = ['string2', 'string3']
xmlParser(newData)
newData = ['string4', 'string5']
xmlParser(newData)

这是输出结果:

$ python test.py
string1
string2
string3
string4
string5

如果在xmlToDictionary里面没有抛出任何异常,这个循环会处理所有的元素。如果你想检查是否会抛出异常,可以试试这个代码:

def xmlParser(self, newData):
     print newData
     for string in newData:
         try:
             if 'a' in string:
                 print 'string1 being processed'
                 xmlToDictionary(string, 'string1')
             # ...
             elif 'e' in string:
                 print 'string5 being processed'
                 xmlToDictionary(string, 'string5')
          except:
             print "excetion error"

也许测试条件并不是你想要的:

如果字符串中包含'a':

希望我能帮到你

3

因为TCP是一个数据流,所以我通常不能单独接收到每个字符串。

你不能可靠地、可预测地单独接收它们。TCP会把数据变成一个连续的数据流。这就是TCP/IP必须做到的。它必须进行缓冲,以创建一个“数据流”,无论你在发送或接收时做什么尝试去“分开”它们。使用TCP/IP时,“分开”这个概念是没有意义的。

你必须在你的端点上根据某些特征来拆分字符串,比如语法、标点符号或者其他什么东西。

通常,我们会把5个XML字符串合并成一个完整的XML消息。

<message>
    <string1>...</string1>
    <string2>...</string2>
    <string3>...</string3>
    <string4>...</string4>
    <string5>...</string5>
</message>        

然后解析这个消息,找到你的五个字符串。这样做简单多了,而且也符合TCP/IP的实际工作方式。

1

这个问题真让人头疼。特别是因为你没有贴出真实的代码,而是你自己对代码应该如何工作的理解。既然这个理解没有问题,你的例子也就没有问题。

不过,我还是把你的代码复制出来,然后尝试修改它以得到你的结果。我认为最可能的问题是,你的代码在处理string4时出现了一些不好的副作用。你的描述听起来很像是在遍历一个列表时对它进行了修改。这里有一个例子,会导致你描述的那种行为:

elif 'd' in string: 
    print 'string4 being processed' 
    # undesirable side effect occurs here
    newData.remove(string)
    xmlToDictionary(string, 'string4') 

试着发送一个像[string4, string1]这样的序列,看看string1是否能通过。如果不能,那很有可能是这段代码出现了某种副作用。

撰写回答