물체 파괴에 대한 내부 pysqlite 연결을 정리합니다
-
13-09-2019 - |
문제
평생 동안 활성화 된 내부 데이터베이스 연결이있는 객체가 있습니다. 프로그램 실행이 끝나면 연결을 커밋하고 닫아야합니다. 지금까지 나는 명백한 것을 사용했습니다 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 앱의 최상위로 만들어졌으며 일반적으로 데이터베이스와 같은 리소스가 획득되는 곳이므로.