psycopg2:光标已关闭

问题描述 投票:0回答:3

我正在使用

psycopg2 2.6.1
。我有一堆查询需要按顺序执行。

conn = psycopg2.connect(database=redshift_database,
                        user=redshift_user,
                        password=os.environ.get("PGPASSWORD"),
                        host=redshift_cluster,
                        port=redshift_port)
cursor = conn.cursor()

queries = [q1, q2, q3....] ## a list of queries 
for query in queries:
    try:
        cursor.execute(query)
    except:
        print e.message

假设

q1
SSL connection has been closed unexpectedly
而失败。然后我的其余查询也失败并显示
cursor already closed
。如何确保如果一个查询失败,则后续查询能够成功执行。

python postgresql psycopg2
3个回答
37
投票

大概如果连接已断开,您需要重新建立它并在异常处理程序中获取另一个光标:

for query in queries:
    try:
        cursor.execute(query)
    except Exception as e:
        print e.message
        conn = psycopg2.connect(....)
        cursor = conn.cursor()

您应该更具体地说明您捕获的例外情况。假设如果光标以某种方式关闭,则出现

InterfaceError
异常,您可以像这样捕获它:

except psycopg2.InterfaceError as e:

可能还有其他不太严重的问题会阻止后续查询的执行,例如交易被中止。在这种情况下,您需要回滚当前事务,然后尝试下一个查询:

queries = ['select count(*) from non_existent_table', 'select count(*) from existing_table']
for query in queries:
    try:
        cursor.execute(query)
    except psycopg2.ProgrammingError as exc:
        print exc.message
        conn.rollback()
    except psycopg2.InterfaceError as exc:
        print exc.message
        conn = psycopg2.connect(....)
        cursor = conn.cursor()

这里尝试对不存在的表进行查询。会引发

ProgrammingError
异常,如果要尝试另一个查询,则必须回滚连接。第二个查询应该成功。

这掩盖了异常处理程序本身引发的进一步异常的详细信息,例如,

connect(...)
在尝试重新建立连接时可能会失败,因此您也应该处理它。


6
投票

您应该明确地重新生成除了块中的光标,以防查询的较低级别出现问题:

for query in queries:
    try:
        cursor.execute(query)
    except:
        print e.message
        try:
            cursor.close()
            cursor = conn.cursor()
        except:
            conn.close()
            conn = psycopg2.connect(...)
        cursor = conn.cursor()

0
投票

人们可能犯的一个小错误是光标被命名两次,例如。

cursor1=connection.cursor()
connection.autocommit=True 

# Naming the cursor object for the second time with a different name.

cursor2=connection.cursor()  
connection.autocommit=True 

由于只能有一个游标对象,因此另一个游标对象会覆盖第一个游标对象,如果使用第一个游标对象,则会引发上述异常。

© www.soinside.com 2019 - 2024. All rights reserved.