programing

cx_Oracle 및 예외 처리 - 모범 사례?

lovejava 2023. 6. 18. 10:00

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

자세한 내용:

cx_Oracle

예외를 정기적인 제어 흐름으로 사용하는 것은 어떻습니까?
파이썬 예외 처리가 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