ただし、接続できない場合は、それ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を使用しています。変数が存在するかどうかを確認するにはどうすればよいですか?の上位3つの投票例 フロー制御を使用するかどうかの良い例です。
ネストの例外は良い考えですか?または、このような依存/カスケード例外を処理するためのより良い方法はありますか?
ネストされた例外には何も問題はありません。これも、正常に実行する限りです。あなたのコードを考えてみましょう。すべての例外を削除して、すべてを1つの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を使用することに対する賛成または反対の議論