在数据库关闭时关闭cx_Oracle连接

5 投票
3 回答
28172 浏览
提问于 2025-04-16 13:21

下面这段 cx_Oracle 代码在数据库正常运行时可以正常工作:

#!C:\Python27
import cx_Oracle

try:
    conn = cx_Oracle.connect("scott/tiger@oracle")

    try:
        curs = conn.cursor()
        curs.execute("SELECT dummy FROM sys.dual")
        print curs.fetchone()[0]
    finally:
        curs.close()
finally:
    conn.close()

但是如果在我运行这个脚本的时候数据库恰好宕机,就会出现一个 NameError 错误:

Traceback (most recent call last):
  File "C:\Users\ArtMetzer\Documents\Code\Python\db_conn_test.py", line 14, in <module>
    conn.close()
NameError: name 'conn' is not defined

这我能理解:因为 cx_Oracle 没有成功建立连接,所以变量 conn 从来没有被设置,因此它没有 close() 方法。

在Python中,怎样才能确保你的数据库连接能够关闭,同时又能优雅地处理数据库宕机的情况呢?

像下面这样做在我看来简直是个大麻烦:

finally:
    try:
        conn.close()
    except NameError:
        pass

3 个回答

-3

(这不是一个确切的答案,但评论的格式不太好看)

试试这个:

#!C:\Python27
import cx_Oracle

try:
    conn = cx_Oracle.connect("scott/tiger@oracle")

    try:
        curs = conn.cursor()
        curs.execute("SELECT dummy FROM sys.dual")
        print curs.fetchone()[0]
    finally:
        curs.close()
        conn.close()
except Exception as e:
    print e

虽然不是最理想的,但应该能更好地工作。我也在想为什么要嵌套这么多层。为什么不这样做:

#!C:\Python27
import cx_Oracle

try:
    conn = cx_Oracle.connect("scott/tiger@oracle")
    curs = conn.cursor()
    curs.execute("SELECT dummy FROM sys.dual")
    print curs.fetchone()[0]
    curs.close()
    conn.close()
except Exception as e:
    print e

顺便说一下,我有个假设,就是连接和游标在退出时会自动关闭,所以不需要手动去关闭它们。

1

根据文档,你其实不需要太担心去关闭连接:

https://cx-oracle.readthedocs.io/en/latest/user_guide/connection_handling.html#closing-connections

这里面有一句很重要的话:

另外,你也可以选择让连接在不再被使用时自动清理。这样,cx_Oracle可以按照正确的顺序关闭相关的资源。

13

你可以在开始的时候把 conn 初始化为 None,然后在 finally 代码块中进行测试。这样做是有效的,因为连接只有在打开的时候才会被设置为其他值。所以,如果连接是打开的,就意味着它不是 None;而 None 则意味着连接没有打开。

#!C:\Python27
import cx_Oracle

conn = None
try:
    conn = cx_Oracle.connect("scott/tiger@oracle")

    try:
        curs = conn.cursor()
        curs.execute("SELECT dummy FROM sys.dual")
        print curs.fetchone()[0]
    finally:
        curs.close()
finally:
    if conn is not None:
        conn.close()

撰写回答