0

在函数 sqlPull() 中,我每 5 秒从 MySQL 数据库中提取最近的 5 个条目。在第二个函数 dupCatch() 中,我试图删除与 n 相比在 n+1 SQL pull 中会出现的重复项。我只想保存唯一的元组列表,但现在该函数每五秒打印 5 次相同的元组列表。

用英语我试图用 dupCatch() 做的是从 sqlPull() 中获取数据,初始化并清空列表,如果变量数据中的所有元组不在空列表中,则将其添加到newData 变量,如果不是,则设置 lastPull 等于非唯一元组。

显然,我的功能是错误的,但我不知道如何修复它。

import mysql.connector
import datetime
import requests
from operator import itemgetter
import time

run = True

def sqlPull():
    connection = mysql.connector.connect(user='XXX', password='XXX', host='XXXX', database='MeshliumDB')
    cursor = connection.cursor()
    cursor.execute("SELECT TimeStamp, MAC, RSSI FROM wifiscan ORDER BY TimeStamp DESC LIMIT 5;")
    data = cursor.fetchall()
    connection.close()
    time.sleep(5)
    return data

def dupCatch():
    data = sqlPull()
    lastPull = []
    for (TimeStamp, MAC, RSSI) in data:
        if (TimeStamp, MAC, RSSI) not in lastPull:
            newData = data
        else:
            lastPull = data
        print newData

while run == True:
    dupCatch()

这就是我现在得到的输出:

[(datetime.datetime(2013, 11, 14, 20, 28, 54), u'E0:CB:1D:36:EE:9D', u' 20'), (datetime.datetime(2013, 11, 14, 20, 28, 53), u'00:1E:8F:75:82:35', u' 21'), (datetime.datetime(2013, 11, 14, 20, 28, 52), u'78:E4:00:0C:50:DF', u' 33'), (datetime.datetime(2013, 11, 14, 20, 28, 52), u'00:1E:4C:03:C0:66', u' 26'), (datetime.datetime(2013, 11, 14, 20, 28, 52), u'78:E4:00:0C:50:DF', u' 33')]
[(datetime.datetime(2013, 11, 14, 20, 28, 54), u'E0:CB:1D:36:EE:9D', u' 20'), (datetime.datetime(2013, 11, 14, 20, 28, 53), u'00:1E:8F:75:82:35', u' 21'), (datetime.datetime(2013, 11, 14, 20, 28, 52), u'78:E4:00:0C:50:DF', u' 33'), (datetime.datetime(2013, 11, 14, 20, 28, 52), u'00:1E:4C:03:C0:66', u' 26'), (datetime.datetime(2013, 11, 14, 20, 28, 52), u'78:E4:00:0C:50:DF', u' 33')]
[(datetime.datetime(2013, 11, 14, 20, 28, 54), u'E0:CB:1D:36:EE:9D', u' 20'), (datetime.datetime(2013, 11, 14, 20, 28, 53), u'00:1E:8F:75:82:35', u' 21'), (datetime.datetime(2013, 11, 14, 20, 28, 52), u'78:E4:00:0C:50:DF', u' 33'), (datetime.datetime(2013, 11, 14, 20, 28, 52), u'00:1E:4C:03:C0:66', u' 26'), (datetime.datetime(2013, 11, 14, 20, 28, 52), u'78:E4:00:0C:50:DF', u' 33')]
[(datetime.datetime(2013, 11, 14, 20, 28, 54), u'E0:CB:1D:36:EE:9D', u' 20'), (datetime.datetime(2013, 11, 14, 20, 28, 53), u'00:1E:8F:75:82:35', u' 21'), (datetime.datetime(2013, 11, 14, 20, 28, 52), u'78:E4:00:0C:50:DF', u' 33'), (datetime.datetime(2013, 11, 14, 20, 28, 52), u'00:1E:4C:03:C0:66', u' 26'), (datetime.datetime(2013, 11, 14, 20, 28, 52), u'78:E4:00:0C:50:DF', u' 33')]
[(datetime.datetime(2013, 11, 14, 20, 28, 54), u'E0:CB:1D:36:EE:9D', u' 20'), (datetime.datetime(2013, 11, 14, 20, 28, 53), u'00:1E:8F:75:82:35', u' 21'), (datetime.datetime(2013, 11, 14, 20, 28, 52), u'78:E4:00:0C:50:DF', u' 33'), (datetime.datetime(2013, 11, 14, 20, 28, 52), u'00:1E:4C:03:C0:66', u' 26'), (datetime.datetime(2013, 11, 14, 20, 28, 52), u'78:E4:00:0C:50:DF', u' 33')]
[(datetime.datetime(2013, 11, 14, 20, 28, 54), u'E0:CB:1D:36:EE:9D', u' 20'), (datetime.datetime(2013, 11, 14, 20, 28, 53), u'00:1E:8F:75:82:35', u' 21'), (datetime.datetime(2013, 11, 14, 20, 28, 52), u'78:E4:00:0C:50:DF', u' 33'), (datetime.datetime(2013, 11, 14, 20, 28, 52), u'00:1E:4C:03:C0:66', u' 26'), (datetime.datetime(2013, 11, 14, 20, 28, 52), u'78:E4:00:0C:50:DF', u' 33')]
4

4 回答 4

1

假设您只是想过滤掉相邻的重复,而不是见过的重复......</p>

首先,当您第一次找到 中的元组时lastPull,您将设置lastPull = data. 这意味着所有后续的元组将自动在lastPull.

同时,您正在通过循环设置一个lastPullnewData每次。因此,其中之一将会发生:

  • 如果所有元组都是新的,您将newData(重复)设置而不是更新lastPull
  • 如果第一个元组是新的,但至少有一个元组是重复的,您将设置newData并更新lastPull
  • 如果第一个元组是重复的,您只会更新lastPull.

这不可能是你想要的逻辑。我认为您想使用anyor all,或者将 a放在其中一个条件中并在 the 的子句中break放置相反的内容,但老实说,我不确定您要在这里做什么。elsefor

同时,您的代码print newData每次都通过循环执行一次。因此,对于每个元组,您将打印所有元组。如上所述,如果第一个元组是新的,这将始终是新的,否则是以前的。再说一次,这不是你想要的,但我不确定你想要什么。也许您想print newData在循环之外,而不是每次都通过?

最重要的是,您说您想将内容添加newData列表中,但在您的代码中,您只是一遍又一遍地替换变量。要将事物添加到列表中,您需要调用append它。(或者extend,如果您有一个新事物列表要一次性添加。)

于 2013-11-15T01:46:16.683 回答
1

与其试图弄清楚您的代码试图做什么并修复它,不如回到您的英文描述:

在英语中,我试图用 dupCatch() 做的是从 sqlPull() 中获取数据,初始化并清空列表,如果该元组不在空列表中,则说明变量数据中的所有元组,将其添加到newData 变量,如果不是,则设置 lastPull 等于非唯一元组。

所以:

seen = set()
def dupCatch():
    data = sqlPull()
    new_data = []
    for (TimeStamp, MAC, RSSI) in data:
        if (TimeStamp, MAC, RSSI) not in seen:
            seen.add((TimeStamp, MAC, RSSI))
            new_data.append((TimeStamp, MAC, RSSI))
    print new_data

或者,更简洁地说:

seen = set()
def dupCatch():
    data = sqlPull()
    newData = [row for row in data if row not in seen]
    seen.update(newData)
    print new_data

无论哪种方式,这里的诀窍是我们有一个集合来跟踪我们见过的每一行。所以,对于每一个新行,如果它在那个集合中,我们已经看到它并且可以忽略它;否则,我们不必忽略它,并将其添加到集合中以备后用。

第二个版本只是通过一次过滤所有 5 行来简化事情,然后一次update用所有新行 -ing 集合,而不是逐行进行。

必须是全局的原因seen是全局永远存在,跨越函数的所有运行,因此我们可以使用它来跟踪我们见过的每一行;如果我们将它设置为函数的本地,那么它每次都会是新的,所以我们只会跟踪我们在当前批次中看到的行,这不是很有用。

一般来说,全局变量是不好的。然而,像持久缓存这样的东西是“一般”规则的一个例外。它们的全部意义在于它们不是本地的。如果您有一个有意义的对象模型,seen那么作为任何对象的成员都会dupCatch比作为全局对象更好。如果您有充分的理由将函数定义为另一个函数内的闭包,seen那么作为该闭包的一部分会更好。等等。但除此之外,全局是最好的选择。


如果你重新组织你的代码,你可以让它变得更简单:

def pull():
    while True:
        for row in sqlPull():
            yield row
for row in unique_everseen(pull()):
    print row

… 甚至:

for row in unique_everseen(chain.from_iterable(iter(sqlPull, None))):
    print row

请参阅迭代器和接下来的几个教程部分、itertools文档和David M. Beazley 的演示文稿,以了解最新版本的功能。但对于新手来说,您可能想要坚持使用第二个版本。

于 2013-11-15T01:50:38.167 回答
0

尝试这个:

def dupCatch():
    data = sqlPull()
    lastPull = []
    for x in data:
        if x not in lastPull:
            print(x)
        lastPull.append(x)
于 2013-11-15T01:41:54.377 回答
0

问题是它lastPull是一个局部变量,所以它[]每次都被设置为,并且在函数调用之间不会持续存在。对于您要执行的操作,您应该使用一个类并将最后一次拉动存储在那里:

import mysql.connector
import datetime
import requests
import time

class SqlPuller(object):
    def __init__(self):
        self.last_pull = set()

    def pull(self):
        connection = mysql.connector.connect(user='XXX', password='XXX',
                host='XXXX', database='MeshliumDB')
        cursor = connection.cursor()
        cursor.execute("SELECT TimeStamp, MAC, RSSI FROM wifiscan ORDER BY TimeStamp DESC LIMIT 5;")
        data = cursor.fetchall()
        connection.close()
        return data

    def pull_new(self):
        new_data = []
        data = self.pull()
        for item in data:
            if item not in self.last_pull:
                new_data.append(item)
        self.last_pull = set(data)
        return new_data


if __name__ == "__main__":
    sql_puller = SqlPuller()
    while True:
        for item in sql_puller.pull():
            print(item)
            time.sleep(5)
于 2013-11-15T01:42:07.943 回答