cx_Oracle 및 예외 처리 - 모범 사례?
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()
하지만 예외 처리에 가장 적합한 설계가 무엇인지 잘 모르겠습니다.
저는 저먼, 다음을만듭다니는나▁the다를 .db
연결 오류를 탐지하기 위해 시도 블록 내부의 개체입니다.
안 되면 하만지, 연할수없면다,db
더 아래에는 존재하지 않을 것입니다 - 그래서 제가 설정한 것입니다.db = None
위에. 하지만, 그것이 좋은 관행인가요?
이상적으로는 연결 시 오류, DDL 문 실행 시 오류 등을 파악해야 합니다.
중첩 예외가 좋은 생각입니까?또는 이와 같은 종속적/캐스케이드된 예외를 처리하는 더 나은 방법이 있습니까?
연결 실패. 된 것은 " out " " " "Comment out " 예또한이스부싶종은분고료실다있하습니패연그결를냥트크립예이▁also부▁commented있)다습▁out니분(ion▁the▁failures또한▁()실▁hence▁to▁-패연e▁where▁there,▁script"입니다. 따라서 코멘트아웃되었습니다.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 in Python"이라는 단어를 볼 수 있습니다.
그렇다고 당신이 지나치라는 것은 아니지만, 파이썬은 일반적으로 "허락보다 용서를 구하는 것이 더 쉽다"는 만트라 EAFP를 사용합니다.변수가 있는지 확인하려면 어떻게 해야 합니까?에서 상위 3개의 투표 예를 참조하십시오.흐름 제어를 사용할 수 있는지 여부를 보여주는 좋은 예입니다.
중첩 예외가 좋은 생각입니까?또는 이와 같은 종속적/캐스케이드된 예외를 처리하는 더 나은 방법이 있습니까?
중첩된 예외는 정상적으로 수행하는 한 다시 한 번 잘못된 것이 아닙니다.코드를 고려합니다.모든 예외를 제거하고 전체를 다음과 같이 포장할 수 있습니다.try:... except
차단. 예외가 제기되면 그 예외가 무엇이었는지 알 수 있지만, 무엇이 잘못되었는지 정확히 추적하는 것은 조금 더 어렵습니다.
만약 당신이 실패에 대해 스스로 이메일을 보내고 싶다면 어떻게 됩니까?cursor.execute
▁an 주변에는 가 있어야 합니다.cursor.execute
이 하나의 작업을 수행하기 위해. 다음 .try:...
않으면 가 아무 되고 외부에 알 수 .try:...
예외를 처리하는 것은 무시됩니다.
궁극적으로 모든 예외는 에서 상속됩니다.
또한 스크립트를 그냥 종료하고 싶은 부분(예: 연결 실패)이 있습니다. 따라서 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()
자세한 내용:
예외를 정기적인 제어 흐름으로 사용하는 것은 어떻습니까?
파이썬 예외 처리가 PHP 및/또는 다른 언어보다 효율적입니까?
try catch를 논리 연산자로 사용하는 것에 대한 찬성 또는 반대 주장
데이터베이스 호출 기능에 장식자를 사용하는 것도 고급 해결책입니다.장식자는 오류를 해결하고 데이터베이스 호출을 다시 시도할 수 있는 기능을 사용합니다.오래된 연결의 경우 재조정은 통화를 다시 연결한 후 다시 실행하는 것입니다.여기 저를 위해 일한 장식가가 있습니다.
####### Decorator named dbReconnect ########
#Retry decorator
#Retries a database function twice when the 1st fails on a stale connection
def dbReconnect():
def real_decorator(function):
def wrapper(*args, **kwargs):
try:
return function(*args, **kwargs)
except Exception as inst:
print ("DB error({0}):".format(inst))
print ("Reconnecting")
#...Code for reconnection is to be placed here..
......
#..end of code for reconnection
return function(*args, **kwargs)
return wrapper
return real_decorator
###### Decorate the DB Call like this: #####
@dbReconnect()
def DB_FcnCall(...):
....
Github에 대한 더 자세한 정보: https://github.com/vvaradarajan/DecoratorForDBReconnect/wiki
참고: 연결 풀을 사용하는 경우 연결을 확인하고 오래된 경우 새로 고치는 내부 연결 풀 기술도 문제를 해결합니다.
언급URL : https://stackoverflow.com/questions/7465889/cx-oracle-and-exception-handling-good-practices
'programing' 카테고리의 다른 글
파이썬에서 openpyxl을 사용하여 Excel 스프레드시트에 행 삽입 (0) | 2023.06.18 |
---|---|
여러 .csv 파일을 한 번에 가져오는 방법은 무엇입니까? (0) | 2023.06.18 |
Numpy: 각 행을 벡터 요소로 나눕니다. (0) | 2023.06.18 |
vuex를 사용하여 로컬 스토리지에 저장하는 다크 모드 (0) | 2023.06.18 |
행 가져오기의 Oracle 크기를 더 높게 설정하면 앱 속도가 느려집니까? (0) | 2023.06.18 |