关闭 cx_Oracle 连接,同时允许数据库关闭

发布于 2024-10-20 23:11:56 字数 907 浏览 7 评论 0原文

当数据库启动时,以下 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

The following cx_Oracle code works fine when the database is up:

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

But if the database happens to be down when I run this script, a NameError is raised:

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

This makes sense to me: cx_Oracle wasn't able to instantiate a connection, so the variable conn never got set, and hence has no close() method.

In Python, what's the best way to ensure your database connection closes, while still gracefully handling the condition of a down database?

Doing something like the following seems like a massive kludge to me:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

两仪 2024-10-27 23:11:56

您可以尝试预先将 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()

You can try initializing conn to something like None before-hand and testing that in the finally block. This works because the only place the connection is set to something else is when it is opened. So opened implies non-None and None implies not-opened:

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

根据文档,您实际上不需要费心关闭连接:
https://cx-oracle.readthedocs.io/ en/latest/user_guide/connection_handling.html#looking-connections

重要的一行是:

或者,您可能更愿意在对连接的引用超出范围时自动清理连接。这让 cx_Oracle 以正确的顺序关闭相关资源。

According to the docs, you don't really need to bother closing the connection:
https://cx-oracle.readthedocs.io/en/latest/user_guide/connection_handling.html#closing-connections

The important line being:

Alternatively, you may prefer to let connections be automatically cleaned up when references to them go out of scope. This lets cx_Oracle close dependent resources in the correct order.

や三分注定 2024-10-27 23:11:56

(不完全是一个答案,但评论没有很好的格式)

试试这个:

#!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

顺便说一句,我假设连接和游标将在退出时自动关闭,从而无需显式关闭它们。

(not exactly an answer, but comments don't have nice formatting)

Try this:

#!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

Not ideal, but should work better. I'm also wondering why so much nesting. Why not do this:

#!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

BTW, I have this assumption that the connection and the cursor will close automatically on exit, removing the need to close them explicitly.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文