当前位置: 首页 > 面试题库 >

cx_Oracle和异常处理-好的做法?

酆君墨
2023-03-14
问题内容

我正在尝试使用cx_Oracle连接到Oracle实例并执行一些DDL语句:

db = None
try:
    db = cx_Oracle.connect('username', 'password', 'hostname:port/SERVICENAME')
#print(db.version)
except cx_Oracle.DatabaseError as e:
    error, = e.args
    if error.code == 1017:
        print('Please check your credentials.')
        # sys.exit()?
    else:
        print('Database connection error: %s'.format(e))
cursor = db.cursor()
try:
    cursor.execute(ddl_statements)
except cx_Oracle.DatabaseError as e:
    error, = e.args
    if error.code == 955:
        print('Table already exists')
    if error.code == 1031:
        print("Insufficient privileges - are you sure you're using the owner account?")
    print(error.code)
    print(error.message)
    print(error.context)
cursor.close()
db.commit()
db.close()

但是,我不确定在这里异常处理的最佳设计是什么。

首先,我db在try块内创建对象,以捕获任何连接错误。

但是,如果无法连接,则db不会再存在-这就是我在db = None上面进行设置的原因。但是,这是好习惯吗?

理想情况下,我需要在连接时捕获错误,然后在运行DDL语句时捕获错误,依此类推。

嵌套异常是个好主意吗?还是有更好的方法来处理像这样的依存/级联异常?

另外,有些地方(例如连接失败)我希望脚本终止,因此注释掉了sys.exit()调用。但是,我听说将异常处理用于流控制是不好的做法。有什么想法吗?


问题答案:

但是,如果无法连接,则db不会再存在-这就是我在db = None上面进行设置的原因。但是,这是好习惯吗?

不,设置db = None不是最佳实践。有两种可能性,要么连接到数据库将起作用,要么将它不起作用。

  • 连接到数据库不起作用:

由于引发的异常已被捕获且未重新引发,因此请继续直至到达cursor = db.Cursor()

db == None,因此,TypeError: 'NoneType' object has no attribute 'Cursor'将引发类似的异常。由于已经捕获了数据库连接失败时生成的异常,因此掩盖了失败的原因。

就我个人而言,除非您打算稍后再次尝试,否则我总是会提出连接异常。如何捕捉取决于您自己;如果错误仍然存​​在,我将通过电子邮件发送“去检查数据库”的电子邮件。

  • 连接到数据库确实有效:

该变量db在您的try:... except块中分配。如果该connect方法有效,则将db其替换为连接对象

无论哪种方式,db都不会使用的初始值。

但是,我听说将异常处理用于流控制是不好的做法。

与其他语言不同,Python 确实
将异常处理用于流控制。在回答的最后,我已经链接到有关堆栈溢出和程序员的几个问题,这些问题都提出了类似的问题。在每个示例中,您都会看到“ but but in
Python”一词。

这并不是说您应该精打细算,但是Python通常使用EAFP的口头禅:
“请求宽恕比允许容易。” 我如何检查变量是否存在中投票最多的三个示例?很好地说明了如何同时使用和不使用流量控制。

嵌套异常是个好主意吗?还是有更好的方法来处理像这样的依存/级联异常?

嵌套异常没有任何问题,只要您明智地执行它即可。考虑您的代码。您可以删除所有异常并将整个内容包装在一个try:... except块中。如果引发了异常,那么您就知道它是什么,但是要精确地查明出了什么问题要困难一些。

如果您想通过电子邮件发送电子邮件给自己,会发生cursor.execute什么?cursor.execute为了执行这一任务,您应该有一个例外。然后,您重新引发异常,以便将其捕获在外部try:...。不重新引发代码将导致您的代码继续运行,好像什么都没发生,并且您在外部try:...处理异常的任何逻辑都将被忽略。

最终,所有异常都继承自BaseException

另外,有些部分(例如连接失败)我希望脚本终止,因此注释掉了sys.exit()调用。

添加了一个简单的类以及如何调用它,这大致就是我将要做的事情。如果要在后台运行,那么打印错误是不值得的-
人们不会坐在那里手动寻找错误。无论采用哪种标准方式,都应将其记录下来,并通知适当的人员。由于这个原因,我已经删除了打印内容,并替换为要记录的提醒。

connect方法失败并引发异常时,由于将类拆分为多个函数execute,因此在尝试断开连接后,调用将不会运行且脚本将完成。

import cx_Oracle

class Oracle(object):

    def connect(self, username, password, hostname, port, servicename):
        """ Connect to the database. """

        try:
            self.db = cx_Oracle.connect(username, password
                                , hostname + ':' + port + '/' + servicename)
        except cx_Oracle.DatabaseError as e:
            # Log error as appropriate
            raise

        # If the database connection succeeded create the cursor
        # we-re going to use.
        self.cursor = self.db.cursor()

    def disconnect(self):
        """
        Disconnect from the database. If this fails, for instance
        if the connection instance doesn't exist, ignore the exception.
        """

        try:
            self.cursor.close()
            self.db.close()
        except cx_Oracle.DatabaseError:
            pass

    def execute(self, sql, bindvars=None, commit=False):
        """
        Execute whatever SQL statements are passed to the method;
        commit if specified. Do not specify fetchall() in here as
        the SQL statement may not be a select.
        bindvars is a dictionary of variables you pass to execute.
        """

        try:
            self.cursor.execute(sql, bindvars)
        except cx_Oracle.DatabaseError as e:
            # Log error as appropriate
            raise

        # Only commit if it-s necessary.
        if commit:
            self.db.commit()

然后调用它:

if __name__ == "__main__":

    oracle = Oracle.connect('username', 'password', 'hostname'
                           , 'port', 'servicename')

    try:
        # No commit as you don-t need to commit DDL.
        oracle.execute('ddl_statements')

    # Ensure that we always disconnect from the database to avoid
    # ORA-00018: Maximum number of sessions exceeded. 
    finally:
        oracle.disconnect()

进一步阅读:

cx_Oracle 文件资料

为什么不将异常用作常规控制流?
python异常处理是否比PHP和/或其他语言更有效?
支持或反对使用try
catch作为逻辑运算符的参数



 类似资料:
  • 问题内容: 我对处理Java中的异常有一些疑问。我读了一些,并得到了一些相互矛盾的指导方针。 异常处理的最佳实践 让我们看一下提到的文章: 它指出, 如果“客户端代码无法执行任何操作”, 通常应该避免使用检查的异常。但这到底是什么意思?在GUI中显示错误消息是否是冒充受检查的异常的充分原因?但这将迫使GUI程序员记住记住RuntimeException及其后代以显示潜在的错误信息。 本文提出的第二

  • 我参考了几篇文章来使用为使用Spring的rest api项目创建全局异常处理程序。这样做的目的是在发生异常的情况下向客户端发送正确的格式化响应。在一些文章中,他们在全局异常处理程序中添加了或。我是否应该用替换它,因为此块用于运行时发生的异常? 异常处理程序代码: 错误响应代码: null

  • 本文向大家介绍.NET中的异常和异常处理用法分析,包括了.NET中的异常和异常处理用法分析的使用技巧和注意事项,需要的朋友参考一下 本文较为详细的分析了.NET中的异常和异常处理用法。分享给大家供大家参考。具体分析如下: .NET中的异常(Exception) .net中的中异常的父类是Exception,大多数异常一般继承自Exception。 可以通过编写一个继承自Exception的类的方式

  • 您需要修复网页抛出的异常和在JavaScript中调试错误。 如果你能得到页面异常和JavaScript错误的细节,在实际工作中非常有用 。当页面抛出异常或脚本产生错误时,Console(控制台)面板会提供明确的可靠信息,以帮助您找到并解决问题。 在Console(控制台)面板中,您可以跟踪异常及跟踪导致异常的执行路径,显式地或隐式地捕获它们(或忽略它们),甚至可以设置错误处理程序来自动收集和处理

  • 问题内容: 我正在查看一位同事的代码,但遇到一段类似于以下代码的代码: 我相信没有必要,但我很难证明这一点。如果它更具体(,等等)可能很有意义,但是因为我认为这是不必要的。有人可以给我一些原因,这可能导致什么问题,以及为什么这是不好的做法?还是这个代码可以吗? 问题答案: 该声明是方法合同的一部分。定义合同时,您应始终尽可能 精确 。因此,说是个坏主意。 出于同样的原因,这是不好的做法,因为不好的

  • 我不知道该怎么办。 当我试图从解析器获取语法错误的数量时,它显示0。 编辑: 它返回null。