psycopg2: курсор уже закрыт

я использую 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. Как я могу гарантировать, что если один запрос не выполняется, то следующие запросы выполняются успешно.

2 ответов


предположительно, если соединение упало, вам нужно будет восстановить его и получить другой курсор в обработчике исключений:

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(...) может произойти сбой при попытке восстановить соединение, поэтому вы должны справиться с этим тоже.


вы должны explicitely восстановить курсор в кроме блока в случае, если что-то пошло не так на более низком уровне, что запрос:

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()