sql >> データベース >  >> RDS >> Oracle

cx_Oracleと例外処理-グッドプラクティス?

    ただし、接続できない場合は、db それ以上下には存在しません-そのため、db = Noneを設定しました その上。しかし、それは良い習慣ですか?

    いいえ、db = Noneを設定します ベストプラクティスではありません。データベースへの接続が機能するか機能しないかの2つの可能性があります。

    • データベースへの接続が機能しない:

      発生した例外がキャッチされ、再発生しないため、cursor = db.Cursor()に到達するまで続行します。 。

      db == None 、したがって、TypeError: 'NoneType' object has no attribute 'Cursor'がありません 発生します。データベース接続が失敗したときに生成された例外はすでにキャッチされているため、失敗の理由は偽装されています。

      個人的には、すぐに再試行しない限り、常に接続例外を発生させます。どのようにそれを捕まえるかはあなた次第です。エラーが続く場合は、「データベースを確認してください」と電子メールで送信します。

    • データベースへの接続は機能します:

      変数db try:... exceptで割り当てられます ブロック。 connectの場合 メソッドは機能し、db 接続オブジェクトに置き換えられます。

    いずれにせよ、dbの初期値 使用されることはありません。

    ただし、このようなフロー制御に例外処理を使用することは悪い習慣だと聞きました。

    他の言語とは異なり、Pythonはします フロー制御には例外処理を使用します。私の答えの終わりに、私は同様の質問をするStackOverflowとProgrammersに関するいくつかの質問にリンクしました。すべての例で、「Pythonで」という単語が表示されます。

    船外に出るべきだと言っているわけではありませんが、Pythonは一般的にEAFPというマントラを使用しています。「許可よりも許しを求める方が簡単です。」 変数が存在するかどうかを確認するにはどうすればよいですか?フロー制御を使用するかどうかの良い例です。

    ネストの例外は良い考えですか?または、このような依存/カスケード例外を処理するためのより良い方法はありますか?

    ネストされた例外には何も問題はありません。これも、正常に実行する限りです。あなたのコードを考えてみましょう。すべての例外を削除して、すべてをtry:... exceptでラップすることができます。 ブロック。例外が発生した場合、それが何であったかはわかりますが、何が悪かったのかを正確に追跡するのは少し困難です。

    cursor.executeの失敗について自分自身に電子メールを送信したい場合はどうなりますか ? cursor.executeの周りに例外があるはずです この1つのタスクを実行するために。次に、例外を再発生させて、外部の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や他の言語よりも効率的ですか?
    論理演算子としてtrycatchを使用することの賛否両論



    1. OracleのCASEステートメントを含む条件付きWHERE句

    2. 以前のnull以外の値を効率的に選択するにはどうすればよいですか?

    3. OracleStreamsのステップバイステップのレプリケーションの例

    4. android.database.sqlite.sqliteconstraintexceptionエラーコード19制約の挿入エラーが失敗しました