문제

평생 동안 활성화 된 내부 데이터베이스 연결이있는 객체가 있습니다. 프로그램 실행이 끝나면 연결을 커밋하고 닫아야합니다. 지금까지 나는 명백한 것을 사용했습니다 close 방법이지만, 특히 호출 코드에서 예외가 발생할 수있는 경우 다소 번거 롭습니다.

나는 사용을 고려하고있다 __del__ 마감 방법이지만 온라인을 읽은 후에는 우려가 있습니다. 이것이 유효한 사용 패턴입니까? 내부 리소스가 해제 될 수 있는지 확인할 수 있습니까? __del__ 바르게?

이 토론 비슷한 질문을 제기했지만 만족스러운 대답은 찾지 못했습니다. 나는 명백한 것을 원하지 않습니다 close 방법 및 사용 with 내 객체는 단순히 오픈 플레이 클로스처럼 사용되지 않지만 GUI에서 실행 중에 사용하는 다른 큰 물체의 구성원으로 유지되기 때문에 옵션이 아닙니다.

C ++는 자원을 안전하게 자유롭게 자유롭게 무료로 제공 할 수있는 파괴자를 완벽하게 작동 시켜서 Python에도 합의 된 것이 있다고 생각합니다. 어떤 이유로 든 그것은 사실이 아닌 것 같고, 공동체의 많은 사람들은 __del__. 그렇다면 대안은 무엇입니까?

도움이 되었습니까?

해결책

모듈은 전체 응용 프로그램에서 동일한 객체를 유지하고 기능을 등록하기 때문에 연결 모듈을 만들 수 있습니다. atexit 기준 치수

# db.py:
import sqlite3
import atexit

con = None

def get_connection():
    global con
    if not con:
        con = sqlite3.connect('somedb.sqlite')
    atexit.register(close_connection, con)
    return con

def close_connection(some_con):
    some_con.commit()
    some_con.close()

# your_program.py
import db
con = db.get_connection()
cur = con.cursor()
cur.execute("SELECT ...")

이 소거는 응용 프로그램의 연결이 모듈 글로벌이 잘 제공하는 단일 인스턴스 (싱글 톤)처럼 보인다는 가정을 기반으로합니다.

그렇지 않은 경우 소멸자를 사용할 수 있습니다.

그러나 파괴자는 쓰레기 수집가 및 원형 참조와 잘 어울리지 않습니다 (소멸자가 호출되기 전에 원형 참조를 직접 제거해야 함). 그렇지 않은 경우 (여러 연결이 필요) 소멸자로 갈 수 있습니다. 원형 참고 문헌을 유지하지 마십시오. 그렇지 않으면 스스로를 깰 필요가 있습니다.

또한 C ++에 대해 말한 것은 잘못입니다. C ++에서 파괴자를 사용하는 경우 객체를 정의하는 블록 (Python 's). with) 또는 당신이 사용할 때 delete 키워드 (이는 생성 된 개체를 처리합니다 new). 그 밖에서 당신은 명백한 것을 사용해야합니다 close() 그것은 소멸자가 아닙니다. 따라서 파이썬과 같습니다. 파이썬은 쓰레기 수집가가 있기 때문에 "더 나은"것입니다.

다른 팁

에서 읽으십시오 ~와 함께 성명. 사용 사례를 설명하고 있습니다.

"Context Manager"클래스에서 연결을 래핑해야합니다. __enter__ 그리고 __exit__ methods used by the with 성명.

보다 PEP 343 자세한 내용은.


편집하다

"내 객체는 단순히 개방형 클로즈처럼 사용되지 않지만 다른 큰 물체의 구성원으로 유지됩니다."

class AnObjectWhichMustBeClosed( object ):
    def __enter__( self ):
        # acquire
    def __exit__( self, type, value, traceback ):
        # release
    def open( self, dbConnectionInfo ):
        # open the connection, updating the state for __exit__ to handle.

class ALargerObject( object ):
    def __init__( self ):
        pass
    def injectTheObjectThatMustBeClosed( self, anObject ):
        self.useThis = anObject

class MyGuiApp( self ):
    def run( self ):
        # build GUI objects
        large = ALargeObject()
        with AnObjectWhichMustBeClosed() as x:
            large.injectTheObjectThatMustBeClosed( x )
            mainLoop()

어떤 사람들은 이것을 "의존성 주입"과 "통제의 역전"이라고 부릅니다. 다른 사람들은 이것을 이것을 부릅니다 전략 무늬. "MustBeclosclosed"는 더 큰 물체에 연결된 전략입니다. 어셈블리는 GUI 앱의 최상위로 만들어졌으며 일반적으로 데이터베이스와 같은 리소스가 획득되는 곳이므로.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top