Python 在一个数组上进行迭代的行为就像在迭代过程中修改数组一样,而这并没有发生

Python 在一个数组上进行迭代的行为就像在迭代过程中修改数组一样,而这并没有发生,python,Python,我正在用python为气象站编写一些软件。每分钟,每分钟都会从传感器中获取新值(这些值实际上是从每分钟更新的文件中获取的)并添加到阵列中。此数组中的项目将上载到联机数据库。例如,如果internet连接中断,阵列将充当缓冲区,以阻止更新版本覆盖当前最新数据。当连接恢复时,可以上载阵列中的所有项目,并且不会丢失任何内容。数组的填充在单独的线程中进行 回到主线程上,在制作阵列副本一分钟后1秒。然后对该副本进行迭代,并将每个项目上载到数据库。上载项后,将从原始数组中删除该项,但不会从副本中删除该项,以

我正在用python为气象站编写一些软件。每分钟,每分钟都会从传感器中获取新值(这些值实际上是从每分钟更新的文件中获取的)并添加到阵列中。此数组中的项目将上载到联机数据库。例如,如果internet连接中断,阵列将充当缓冲区,以阻止更新版本覆盖当前最新数据。当连接恢复时,可以上载阵列中的所有项目,并且不会丢失任何内容。数组的填充在单独的线程中进行

回到主线程上,在制作阵列副本一分钟后1秒。然后对该副本进行迭代,并将每个项目上载到数据库。上载项后,将从原始数组中删除该项,但不会从副本中删除该项,以防止在对其进行迭代时操作所导致的错误。如果上传任何项目时发生错误,则整个迭代将停止,并在下一分钟继续,以保留数据库中的数据年表。这是线程安全的,因为我正在从原始数组中删除,但我正在迭代它的一个副本,并且我在代码中的任何地方都没有发现线程方面的问题

然而,我遇到了一个很难消除的问题,这个问题看起来像是在迭代列表时修改列表时会发现的问题,即使这种情况在任何地方都不会发生。当每分钟提供一条数据(这是正常操作)时,一切都可以正常上传。此外,如果阵列中有两个项目(通过断开internet连接一分钟完成),它也可以正常工作。两个项目都按正确的顺序上载。但是,如果列表中有两个以上的项目需要上传(互联网关闭超过一分钟),那么迭代似乎会跳过列表中的其他所有项目。这将导致上载其他所有项目,然后上载阵列中剩余项目的其他所有项目,依此类推,直到阵列恢复为正常的每分钟一个项目。这会导致数据库中的上载出现故障

我已经将错误缩小到从uploadBuffer数组中删除项目的行,因为没有这一行,它可以正常工作(显然,项目在上传后不会从缓冲区中删除)。我看不出这个问题是如何存在的,因为我正在迭代原始列表的副本。从原始列表中删除项时使用的是它的值,而不是它的索引,所以这不是问题所在。此外,原始数组的副本在迭代开始之前制作一次,因此我不知道从原始数组中删除项会如何影响副本上的迭代

我真的很想把它修好,因为我已经尝试了两个多星期,没有运气,所以谢谢你的帮助,我的代码如下。另外,如果您注意到我如何使用线程锁的任何问题,请说明,因为我不完全确定我是否正确使用了线程锁

import urllib2
from lxml import etree
import os
import datetime
import time
import httplib
import socket
import threading

timeFormat = "%d/%m/%Y at %H:%M:%S.%f"
rollingData = "/home/pi/weatherstation/other/latest.xml"
bufferLock = threading.Lock()

print("MOD_UPLOAD: file watching started on " +
      datetime.datetime.now().strftime(timeFormat))
uploadBuffer = []

def watchForReport():
    previousModified = os.stat(rollingData)[8]

    while True:
        try:
            currentModified = os.stat(rollingData)[8]

            # New data needs to be uploaded
            if not currentModified == previousModified:
                newData = open(rollingData, "r").read()

                bufferLock.acquire()
                uploadBuffer.append(newData)
                bufferLock.release()

                previousModified = currentModified

        except:
            print("OSError")

# Watch for new data in separate thread
threading.Thread(target = watchForReport).start()


while True:
    currentSecond = datetime.datetime.now().strftime("%S")

    if currentSecond == "01" or currentSecond == "02":
        if bufferLock.locked() == False:

            bufferLock.acquire()
            bufferCopy = uploadBuffer
            bufferLock.release()

            # If there are records to be uploaded
            if len(bufferCopy) > 0:

                for item in bufferCopy:
                    print("\nreport: " + item[:35])
                    print("bufferCount: " + str(len(bufferCopy)))

                    if item == "":
                        # This isn't the problem, as the text 'empty' is almost never printed
                        print("empty")
                        bufferCopy.remove(item)
                        break
                    else:
                        report = etree.fromstring(item)

                    # Separate date and time and format
                    timestamp = report.xpath("@time")[0]

                    tDate = timestamp.rsplit("T", 2)[0]
                    tTime = timestamp.rsplit("T", 2)[1]
                    tTime = tTime.replace(":", "-")

                    # Generate URL to write data to the database
                    url = "http://www.example.com/uploadfile.php?date="
                    url += tDate + "&time=" + tTime + "&shieldedtemp="
                    url += report.xpath("@shieldedtemp")[0] + "&exposedtemp="
                    url += report.xpath("@exposedtemp")[0] + "&soil10temp="
                    url += report.xpath("@soil10temp")[0] + "&soil30temp="
                    url += report.xpath("@soil30temp")[0] + "&soil100temp="
                    url += report.xpath("@soil100temp")[0]

                    try:
                        # Upload report to database
                        response = urllib2.urlopen(url, timeout = 9).read()
                        print("response: " + response)

                        # Response[4] means success
                        if response == "response[4]":
                            bufferLock.acquire()
                            # Thus is the line causing the problem:
                            uploadBuffer.remove(item)
                            bufferLock.release()

                        else:
                            # Break out of loop on failure to preserve chronology
                            break

                    except urllib2.HTTPError:
                        print("urllib2.HTTPError")
                        print("bufferReCount: " + str(len(bufferCopy)))
                        break

                    except httplib.BadStatusLine:
                        print("httplib.BadStatusLine")
                        print("bufferReCount: " + str(len(bufferCopy)))
                        break

                    except urllib2.URLError:
                        print("urllib2.URLError")
                        print("bufferReCount: " + str(len(bufferCopy)))
                        break

                    except socket.timeout:
                        print("timeout")
                        print("bufferReCount: " + str(len(bufferCopy)))
                        break

                    print("bufferReCount: " + str(len(bufferCopy)))

bufferCopy=uploadBuffer
不是副本。请将其更改为:
bufferCopy=uploadBuffer[:]
@alfasin谢谢,我想它可能是那样的小东西!我明天有空就试试time@alfasin很好用,谢谢。那行在那之前做了什么?@HenryHunt它只是复制对列表的引用,而不是列表本身。