Что происходит с открытым курсором после отката транзакции в Postgres с помощью Psycopg2? - PullRequest
0 голосов
/ 22 октября 2019

Я пытаюсь скопировать список CSV файлов в Postgres , используя Psycopg2's copy_expert().

Я открываю курсорвыполнить команду копирования для каждого файла отдельно и закрыть его после копирования данных. Но, если я получаю какую-либо ошибку для любого файла в этом процессе, я откатываю транзакцию.

Если я получаю ошибку, я не уверен, что произойдет с курсором, который я открыл ранеекопирование файла CSV .

Будет ли он автоматически закрыт после выполнения * отката 1017 * для соединения или он останется таким же?

Я проверил документы на откат на psycopg2 http://initd.org/psycopg/docs/connection.html#connection.rollback. Но, тем не менее, я не уверен, что происходит с курсором, который не был закрыт, так как они не упомянули ничего, связанного скурсор в документах.

try:
    for tablename, filename in self.mapping:
        cur = self.conn.cursor()
        filename = f"{self.to_db}{wid}-{filename}"
        filename = f"{os.path.join(self.directory, filename)}.csv"
        sql = f"copy {tablename} from stdin with delimiter as ',' csv header;"
        with open(f"{filename}", 'r') as file:
            cur.copy_expert(sql, file)
        cur.close()
    self.conn.commit()
except Exception as e:
    self.conn.rollback()
    return e

1 Ответ

1 голос
/ 25 октября 2019

Вы можете использовать менеджер контекста курсора, когда код покидает блок with, курсор автоматически закрывается.
Поскольку вы запускаете коммит после цикла for, в этом нет необходимости 'пересоздавать курсор при каждой итерации цикла.

class foo():
    def __init__(self):
        self.conn = psycopg2.connect('host=...')

    def whatever(self):
        with self.conn.cursor() as cur:
            try:
                for tablename, filename in self.mapping:
                    filename = f"{self.to_db}{wid}-{filename}"
                    filename = f"{os.path.join(self.directory, filename)}.csv"
                    sql = f"copy {tablename} from stdin with delimiter as ',' csv header;"
                    with open(f"{filename}", 'r') as file:
                        cur.copy_expert(sql, file)
                self.conn.commit()
            except Exception as e:
                self.conn.rollback()
                return e
...