ich habe ein kleines Problem mit der gedanklichen Ordnung. Fangen wir erst einmal an. Wir sehen hier zwei Klassen, die diesen Context-Manager-Protokoll unterstützen. Soweit so gut. Was habe ich nun vor? Ich möchte (wie man anhand der View-Klasse sieht) dem Benutzer die Möglichkeit geben, dass er/sie sich komplett von der Datenbank abmelden kann. Das Programm muss aber nicht geschlossen werden. Kann ja sein, dass er sich denkt: "Arbeite später mal weiter, muss jetzt schwimmen gehen". Nur alle Verbindungen sollen also geschlossen werden. Daher habe ich einmal die Engine und die Session in zwei separate Klassen untergebracht. In Zeile 135 bis 139 sehen wir, dass mit der with-Anweisung ein Engine-Objekt erzeugt wird, und anschließend wird ein Session-Objekt erzeugt, das dann das Engine-Objekt übergeben bekommt.
Jetzt kommen wir zum Problem. In meinem Beisiel möchte ich simulieren, dass die Verbindung solange aufrecht erhalten wird, bist die with-Anweisung verlassen wird. Dies soll geschehen, sobald der Benutzer auf "Abmelden" oder "Disconnect" klickt. Bis dahin wird die with-Anweisung der Engine durch die While-Schleife aufrecht erhalten. Wie und wo bringe ich die Engine unter, damit diese während der Arbeit nicht blockiert? Denn ich muss ja auch bedenken, dass ich an unterschiedlichen Stellen meines Programms (wir stellen uns mehrere Eingabefenster vor) die Session brauche. Das heißt, ich stehe jetzt vor dem Überlegungs-Problem. Wie kriege ich diese beiden Klassen unter deinem Hut, so dass die While-Schleife niemanden blockiert, und damit ich auch während dessen mit der Session an verschiedenen Stellen arbeiten kann?
Ich hoffe, ich konnte mein Problem halbwegs erklären.
Code: Alles auswählen
from sys import argv
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from sqlalchemy.exc import SQLAlchemyError
from PyQt4.QtCore import QObject, pyqtSignal, QThread, Qt
from PyQt4.QtGui import QDialog, QApplication, QPushButton, \
QLineEdit, QFormLayout, QTextEdit
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=None, dbdriver=None,
dbuser=None, dbuser_pwd=None,
db_server_host=None, dbport=None, db_name=None):
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()
class Form(QDialog):
finish = pyqtSignal()
test_it = pyqtSignal()
def __init__(self, parent=None):
QDialog.__init__(self, parent)
self.engine = None
self.logged_in = True
self.init_ui()
def init_ui(self):
self.db_localhost = QLineEdit()
self.db_localhost.setText("localhost")
self.db_user = QLineEdit()
self.db_user.setText("root")
self.db_user_pwd = QLineEdit()
self.db_user_pwd.setText("password")
self.db_name = QLineEdit()
self.db_name.setText("test")
self.db_port = QLineEdit()
self.db_port.setText("3306")
self.text_edit_status = QTextEdit()
self.pushButton_connection = QPushButton()
self.pushButton_connection.setText("Connect")
self.pushButton_disconnection = QPushButton()
self.pushButton_disconnection.setText("Disconnect")
self.pushButton_close = QPushButton()
self.pushButton_close.setText("Close")
layout = QFormLayout()
layout.addWidget(self.db_localhost)
layout.addWidget(self.db_user)
layout.addWidget(self.db_user_pwd)
layout.addWidget(self.db_name)
layout.addWidget(self.db_port)
layout.addWidget(self.text_edit_status)
layout.addWidget(self.pushButton_connection)
layout.addWidget(self.pushButton_disconnection)
layout.addWidget(self.pushButton_close)
self.setLayout(layout)
self.setWindowTitle("Log In")
self.init_signal_slot_pushButton()
def log_in(self):
try:
self._engine = Engine(dbms='mysql',
dbdriver='pymysql',
dbuser=unicode(self.db_user.text()),
dbuser_pwd=unicode(self.db_user_pwd.text()),
db_server_host=unicode(self.db_localhost.text()),
dbport=unicode(self.db_port.text()),
db_name=unicode(self.db_name.text()))
self.text_edit_status.setText("Connecting to the database... please wait!")
with self._engine as engine:
while logged_in:
with Session(engine) as session:
pass
# do_stuff()
except TypeError as err:
self.text_edit_status.setText((str(err)))
def log_out(self):
pass
def init_signal_slot_pushButton(self):
self.pushButton_connection.clicked.connect(self.log_in)
self.pushButton_disconnection.clicked.connect(self.log_out)
self.pushButton_close.clicked.connect(self.close)
def button_click(self):
pass
app = QApplication(argv)
form = Form()
form.show()
app.exec_()