cx_Oracle.DatabaseError: DPI-1039: оператор уже закрыт - PullRequest
0 голосов
/ 04 июня 2019

Обновлен до последней версии Cx_Oracle (5.1.3 до 7.1.3), и теперь весь мой код не работает. Кажется, проблема возникает при попытке передать курсор.

def select_query_remy(self,sql,params=None):
    with cx_Oracle.connect(self.connection) as con:
        cur = con.cursor()
        if params:
            cur.execute(sql,params)
        else:
            cur.execute(sql)
        #print cur.fetchall()
        return cur

Я получаю правильные данные в fetchall, поэтому я знаю, что он правильно подключается и возвращает правильный результат. Поэтому я это комментирую.

В других скриптах, которые я называю, строки должны теперь правильно хранить курсор?

rows = con.select_query_remy(sql)

Когда я fetchall() из другого скрипта, я получаю ниже и получаю ошибку.

print rows.fetchall()

cx_Oracle.DatabaseError: DPI-1039: оператор уже закрыт

Есть идеи?

полный дБ.py

import cx_Oracle

class db:

list ={}    

def __init__(self):
    '''
        AMFM Python DB connectors
   '''
    db.list["disprod"] = [999,"disprod.prod.com"]
    db.list["prodqry"] = [999,"prodqry.prod.com"]
    db.list["amfmprod"] = [999,"amfmprod.prod.com"]
    db.list["esriprod"] = [999,"esriprod.prod.com"]
    db.list["amfmtest"] = [999,"amfmtest.prod.com"]
    db.list["amfmdev"] = [999,"CCTdAMFM.prod.com"]
    db.list["amfmtran"] = [999,"amfmtran.prod.com"]


def setup(self,env, username, password):
    self.username = username
    self.password = password
    self.env = env

    self.port = db.list[env][0]
    self.ip = db.list[env][1]
    if env == "prodqry":
        self.env = "prodqry.world"
    elif env == "amfmprod":
        self.env = "amfmprod.world"
    elif env == "esriprod":
        self.env = "esriprod.world"
    else:
        self.env = env
    self.connection = self.username+"/"+self.password+"@"+self.ip+":"+str(self.port)+"/"+self.env

def select_query_remy(self,sql,params=None):
    with cx_Oracle.connect(self.connection) as con:
        cur = None
        cur = con.cursor()
        if params:
            cur.execute(sql,params)
        else:
            cur.execute(sql)
        return cur

В другом питоне я создаю новую БД и пытаюсь вернуть курсор назад.

con = db()
con.setup("xxx","user","password")
rows = con.select_query_remy(sql)
print rows.fetchall()

Результат:

Traceback (most recent call last):
  File "C:\Python27\ArcGIS10.5\test\test.py", line 30, in <module>
    print rows.fetchall()
cx_Oracle.DatabaseError: DPI-1039: statement was already closed

Если я верну fetchall (), данные будут найдены. Когда я передаю курсор сам по себе, возникает ошибка.

def select_query_remy(self,sql,params=None):
        with cx_Oracle.connect(self.connection) as con:
            cur = None
            cur = con.cursor()
            if params:
                cur.execute(sql,params)
            else:
                cur.execute(sql)
            #return cur
            return cur.fetchall()

Есть идеи, почему я не могу пропустить курсор, как это было в прошлом?

1 Ответ

0 голосов
/ 04 июня 2019

Ваша ошибка связана с with -блоком (также известным как менеджер контекста ). Позвольте мне добавить пару комментариев к функции select_query_remy:

def select_query_remy(self,sql,params=None):
    with cx_Oracle.connect(self.connection) as con:  # connects to database
        cur = None
        cur = con.cursor()
        if params:
            cur.execute(sql,params)
        else:
            cur.execute(sql)
        return cur                                # closes connection (invalidates cursor too!)    

Поскольку with -блок управляет контекстом соединения с базой данных, соединение будет закрыто после выхода из блока.

Чтобы исправить ошибку, я предлагаю выполнить fetchall внутри функции напрямую , а затем работать с этими данными вне функции. (Вы уже поняли это.)

Дополнительная литература: Справочник по языку Python: with оператор

...