如何在Python中读取cx_Oracle.LOB数据?

如何在Python中读取cx_Oracle.LOB数据?,python,cx-oracle,Python,Cx Oracle,我有以下代码: dsn = cx_Oracle.makedsn(hostname, port, sid) orcl = cx_Oracle.connect(username + '/' + password + '@' + dsn) curs = orcl.cursor() sql = "select TEMPLATE from my_table where id ='6'" curs.execute(sql) rows = curs.fetcha

我有以下代码:

    dsn = cx_Oracle.makedsn(hostname, port, sid)
    orcl = cx_Oracle.connect(username + '/' + password + '@' + dsn)
    curs = orcl.cursor()
    sql = "select TEMPLATE from my_table where id ='6'"
    curs.execute(sql)
    rows = curs.fetchall()
    print rows
    template = rows[0][0]
    orcl.close()
    print template.read()
当我打印行时,我得到以下信息:

[(<cx_Oracle.LOB object at 0x0000000001D49990>,)]
[(,)]
但是,当我打印template.read()时,会出现以下错误:

cx_Oracle.DatabaseError:无效句柄


我如何获取和读取这些数据?谢谢。

想明白了。我必须这样做:

curs.execute(sql)        
for row in curs:
    print row[0].read()

我发现,在使用cx_Oracle.LOB.read()方法之前关闭与Oracle的连接时,会发生这种情况

orcl = cx_Oracle.connect(usrpass+'@'+dbase)
c = orcl.cursor()
c.execute(sq)
dane =  c.fetchall()

orcl.close() # before reading LOB to str

wkt = dane[0][0].read()
我得到:数据库错误:无效句柄
但以下代码是有效的:

orcl = cx_Oracle.connect(usrpass+'@'+dbase)
c = orcl.cursor()
c.execute(sq)
dane =  c.fetchall()

wkt = dane[0][0].read()

orcl.close() # after reading LOB to str

基本上,您必须遍历fetchall对象

dsn = cx_Oracle.makedsn(hostname, port, sid)
orcl = cx_Oracle.connect(username + '/' + password + '@' + dsn)
curs = orcl.cursor()
sql = "select TEMPLATE from my_table where id ='6'"
curs.execute(sql)
rows = curs.fetchall()
for x in rows:
   list_ = list(x)
   print(list_)

for循环中应该有一个额外的逗号,请参见下面的代码,我在for循环中的x后面提供了一个额外的逗号

dsn = cx_Oracle.makedsn(hostname, port, sid)
orcl = cx_Oracle.connect(username + '/' + password + '@' + dsn)
curs = orcl.cursor()
sql = "select TEMPLATE from my_table where id ='6'"
curs.execute(sql)
rows = curs.fetchall()
for x, in rows:
    print(x)

在一个稍微不同的环境中,我也有同样的问题。我需要查询一个+27000行的表,结果发现cx_Oracle在一段时间后切断了与DB的连接

当与数据库的连接打开时,可以使用cx_Oracle.Lob对象的read()方法将其转换为字符串。但是,如果查询带来的表太大,它将无法工作,因为连接将在某个点停止,并且当您想要从查询中读取结果时,您将在cx_Oracle对象上发现错误

我尝试了很多东西,比如设置 connection.callTimeout=0(根据文档,这意味着它将无限等待),使用fetchall()然后将结果放在数据帧或numpy数组上,但我永远无法读取cx_Oracle.Lob对象

如果我尝试使用pandas.DataFrame.read_sql(查询,连接)运行查询,则数据框将包含连接关闭的cx_Oracle.Lob对象,使它们无用。(同样,只有当桌子很大时才会发生这种情况)

最后,我找到了一种绕过这个问题的方法,在中间查询并创建一个csv文件,尽管我知道这并不理想

def csv_from_sql(sql: str, path: str="dataframe.csv") -> bool:
try: 
    with cx_Oracle.connect(config.username, config.password, config.database, encoding=config.encoding) as connection:
        connection.callTimeout = 0
        data = pd.read_sql(sql, con=connection)
        data.to_csv(path)
        print("FILE CREATED")
except cx_Oracle.Error as error: 
    print(error)
    return False
finally: 
    print("PROCESS ENDED\n")
    return True

def make_query(sql: str, path: str="dataframe.csv") -> pd.DataFrame:
if csv_from_sql(sql, path):
    dataframe = pd.read_csv("dataframe.csv")
    return dataframe
return pd.DataFrame()
这花了很长时间(大约4到5分钟)才打开我的+27000行表格,但在其他一切都不起作用的情况下,它仍然有效


如果有人知道更好的方法,这对我也会有帮助。

知道为什么会这样吗?我甚至不能再重现错误了,但知道这一点很好。谢谢编辑:实际上,我只是复制了它,在我将
orcl.close()
移动到
read()
之后它就工作了。谢谢我做了更多的测试。这只发生在LOB数据上。这真的很有趣。关于这一点,我可能会问另一个问题。代码显示了“流式”LOB,这可能需要对数据库进行多次访问。这意味着在读取LOB之前,连接需要保持打开状态。如果使用更快的方法将LOB获取为字符串(或字节),则不需要这样做。请参阅cx_Oracle文档:如果行为int,则仅需要行[0],以添加到该行中。对于int,没有read()。cx_Oracle不会“断开连接”。可能进程内存不足。可能您达到了DBA强加的用户配置文件/资源管理器限制。查看有关LOB处理的cx\U Oracle文档。(还有,既然你有一个问题,为什么不发布一个新的SO问题,而不是在这里加上标签?)