我想用INSERT和UPDATE修改一些数据。从psycopg教程看起来我需要
cur = connection.cursor()
cur.execute(my_insert_statement)
connection.commit()
Psycopg的cursor class似乎与postgres定义的游标几乎没有关系。
如果我模块化我的脚本,在主模块中创建一个连接和一些工作函数(没有线程,只是为了模块化)我应该
将连接参数传递给函数并每次都重新创建游标。经常创建新游标对象会有很大的开销吗?
def process_log_file(self, connection):
传递连接和游标 - 使函数签名和实现不必要地复杂化
def process_log_file(self, connection, cursor):
仅将游标作为参数传递,并使用mycursor.connection.commit()
进行提交
def process_log_file(self, cursor):
答案 0 :(得分:6)
这三个中的任何一个都会起作用(主要是个人品味),但我更喜欢(1)。原因如下:
cursor
类型是轻量级的,除了创建新的Python对象之外,创建它并没有做任何特别的事情。欢迎您创建,使用(提交/回滚)并销毁任意数量的游标,特别是如果这有助于您保持代码清洁和有条理。
此外,cursor
在您处理需要访问来自多个不同查询的数据的复杂逻辑时非常重要:在这种情况下,游标充当数据的持有者/迭代器。
最后,绕过connection
(你的后端的真实手柄)并将光标保持在特定功能/方法的本地,只是"感觉正确"。
答案 1 :(得分:2)
cursor
支持with
使用模式,该模式会在块完成后自动关闭它们。当您使用游标进行紧凑操作时,这可能是一个非常有用的模式。
在其他时候,可能需要在整个函数中使用游标,或者可能需要使用多个游标,因此在这种情况下,with
模式的含义会更低,并且最好在功能级范围。
还要记住named cursors
的重要性,这是psycopg游标和Postgres游标交织在一起的地方。只需在构造函数调用中赋予name
属性一个值,就会自动获得一个服务器端游标,然后就像任何Python集合一样迭代,并执行分块提取。
块大小可以更改,但默认情况下它会以2000块的形式获取。在查询大型表时这一点尤其重要,因为您可以使用巨大的结果集快速耗尽内存客户端。 psycopg摘要必须直接处理Postgres游标,并在需要时在游标迭代过程中透明地获取下一个块。
请记住,命名游标实际上只能用于一件事 - 然后迭代的查询;如果你尝试在同一个游标上执行另一个查询,它将在内存服务时抛出异常。使用非命名游标,您可以在完成结果后重复使用相同的游标。
我通常使用命名游标来表示我认为甚至可能返回相当大的结果集的任何查询,以及用于小查询和其他命令(如更新,删除,表创建等)的非命名游标。 / p>
答案 2 :(得分:1)
“数据库游标...用于管理获取操作的上下文。”
因此,考虑到模块化,似乎除非你的函数需要先前操作的结果,否则创建新游标并关闭它们或者当它们离开作用域时让它们自己关闭会更有意义。如果你有一个重复多次的操作,并确保重新创建游标会引入开销,你总是可以创建一个包装游标而不是简单辅助函数的辅助类。
但是,你的所有三种方法都可以正常工作。我个人使用样式#2编写代码,但我同意它似乎是最糟糕的代码。