5

我正在开发一个 Trac 插件...

为了检索我的数据,我创建了一个游标对象并获得如下结果表:

 db = self.env.get_db_cnx()
 cursor = db.cursor()
 cursor.execute("SELECT...") 

现在结果被用于 3 个不同的功能。我的问题现在是光标在第一次循环时被清除(就像这里所说的那样http://packages.python.org/psycopg2/cursor.html

然后我尝试复制光标对象,但这也失败了。该copy(cursor)函数似乎有一个大数据集的问题,并且该函数deepcopy(cursor)无论如何都会失败(根据这个错误http://bugs.python.org/issue1515)。

我该如何解决这个问题?

4

2 回答 2

15

存储来自任何有限迭代的值很简单:

results = list(cursor)

遍历可迭代对象并将结果存储在列表中。可以根据需要多次迭代此列表。

您不需要光标的副本,只需要查询结果的副本。

对于这种特定情况,您应该执行 9000 在他的评论中建议的操作——使用游标内置功能来获取列表的结果,这应该与手动调用一样快或更快list

于 2012-04-16T14:09:59.923 回答
0

如果您想避免循环遍历数据额外的时间,您可以尝试将其包装在生成器中:

def lazy_execute(sql, cursor=cursor):
    results = []
    cursor.execute(sql)
    def fetch():
        if results:
            for r in results:
                yield r
            raise StopIteration()
        else:
            for r in cursor:
                results.append(r)
                yield r
            raise StopIteration()

    return fetch

这实质上是根据需要创建一个列表,但可以让您在任何地方安全地调用相同的函数。然后你会像这样使用它:

results = lazy_execute(my_sql):
for r in results():
    "do something with r"

这几乎可以肯定是一种过度设计的过早优化,尽管它确实具有相同名称的优点,在每种情况下都意味着相同的事物,而不是生成一个新列表,然后相同的数据具有两个不同的名称。

我想如果我要争论使用它,我会使用相同名称的论点,除非数据集非常大,但如果它足够重要,那么你很有可能不想将它全部存储在反正内存。

它也完全未经测试。

于 2012-04-16T15:16:47.683 回答