在以下可執行代碼中,您看到一個SessionScope
()類。在main
()中,用戶可以登錄到他的MySQL數據庫服務器。我們在課堂上看看。有兩種神奇的方法(__enter__, __exit__)
, ,它允許我用with
-statement輕鬆使用對象。在此聲明中,您還會看到該程序使用會話。當__exit__
() - 方法調用 時,會話關閉。但是我們知道會將連接返回到Engine的連接池。這意味着,它不會直接關閉連接,因爲連接是共享的,所以 。到現在爲止還挺好。在GUI一側,用戶可以選擇註銷。那麼,讓我們想象一下:經過非常非常非常長的數據庫工作,用戶希望連接真正關閉,但他不希望程序自行關閉。稍後,用戶可能會再次登錄並繼續工作。在此之前,該程序仍在運行,但未連接到數據庫 。用戶不再需要連接。Python 2.7.6:如何正確清理類?
這意味着對於python,我們不再需要SessionScope
()類。在我的情況下,我們可以用del session_scope
刪除/清理這個類。我的想法是重新實現__del__
() - 方法。在這種方法中,我想 關閉連接池的所有連接。如果這個類被清除/刪除,所有的連接都應該斷開,這就是爲什麼我使用log_out
()函數中的del
的原因。
這是正確的方法嗎?
TA,你Sophus
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.exc import SQLAlchemyError
class SessionScope(object):
def __init__(self, dbms, dbdriver, dbuser, dbuser_pwd, db_server_host, dbport, db_name):
self.dbms = dbms
self.dbdriver = dbdriver
self.dbuser = dbuser
self.dbuser_pwd = dbuser_pwd
self.db_server_host = db_server_host
self.dbport = dbport
self.db_name = db_name
url = '{}+{}://{}:{}@{}:{}/{}'.format(
self.dbms, self.dbdriver, self.dbuser, self.dbuser_pwd, self.db_server_host, self.dbport, self.db_name)
self.engine = create_engine(url, encoding='utf8', echo=True)
# store a sessionmaker for this db connection object
self._Session = sessionmaker(bind=self.engine)
self.session = None
def __enter__(self):
self.session = self._Session()
return self._Session()
def __exit__(self, exception, exc_value, traceback):
try:
if exception:
self.session.rollback()
else:
self.session.commit()
finally:
self.session.close()
self.session = None
def __del__(self):
self.engine.dispose()
def log_out(session_scope):
del session_scope
def main():
dbm_system = raw_input("Which DBMS? (type for e.g. mysql): ")
dbm_driver = raw_input("Which db-driver? (type for e.g. pymysql): ")
db_host = raw_input("Server-Host: ")
db_user = raw_input("Database-user: ")
db_passwd = raw_input("User-Password: ")
db_name = raw_input("Database Name: ")
db_port = raw_input("Port: ")
try:
session_scope = SessionScope(dbm_system, dbm_driver, db_user, \
db_passwd, db_host, db_port, db_name)
with session_scope as session:
# Its just for testing.
print session.execute("SELECT VERSION();")
log_out(session_scope)
except SQLAlchemyError as err:
print "ERROR", err[0]
if __name__ == '__main__':
main()
編輯#1:
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.exc import SQLAlchemyError
class SessionScope(object):
def __init__(self, engine):
self.engine = engine
# store a sessionmaker for this db connection object
self._Session = sessionmaker(bind=self.engine)
self.session = None
def __enter__(self):
self.session = self._Session()
return self._Session()
def __exit__(self, exception, exc_value, traceback):
try:
if exception:
self.session.rollback()
else:
self.session.commit()
finally:
self.session.close()
self.session = None
class Engine(object):
def __init__(self, dbms, dbdriver, dbuser, dbuser_pwd, db_server_host, dbport, db_name):
self.dbms = dbms
self.dbdriver = dbdriver
self.dbuser = dbuser
self.dbuser_pwd = dbuser_pwd
self.db_server_host = db_server_host
self.dbport = dbport
self.db_name = db_name
url = '{}+{}://{}:{}@{}:{}/{}'.format(
self.dbms, self.dbdriver, self.dbuser, self.dbuser_pwd, self.db_server_host, self.dbport, self.db_name)
self._Engine = create_engine(url, encoding='utf8', echo=True)
def __enter__(self):
return self._Engine
def __exit__(self, exception, exc_value, traceback):
'''
Make sure the dbconnection gets closed
'''
self._Engine.dispose()
logged_in = True
def main():
dbm_system = raw_input("Which DBMS? (type for e.g. mysql): ")
dbm_driver = raw_input("Which db-driver? (type for e.g. pymysql): ")
db_host = raw_input("Server-Host: ")
db_user = raw_input("Database-user: ")
db_passwd = raw_input("User-Password: ")
db_name = raw_input("Database Name: ")
db_port = raw_input("Port: ")
try:
with Engine(dbm_system, dbm_driver, db_user, \
db_passwd, db_host, db_port, db_name) as engine:
while logged_in:
with SessionScope(engine) as session:
# Its just for testing.
print session.execute("SELECT VERSION();")
except SQLAlchemyError as err:
print "ERROR", err[0]
if __name__ == '__main__':
main()
Blckknght:首先,TA爲你提供幫助。我編輯了我的代碼的新版本(編輯#1)。這是你的意思嗎?那麼在這個新版本中,程序一直執行直到'logged_in'爲False。實際上是不可行的,因爲用戶進行了操縱。實際上我認爲while循環就足夠了,對吧? – Sophus