Python 在另一个脚本上引用数据库连接
Python referencing database connection on another script
我正在深入学习 Python,同时尝试制作一个应用程序,使用存储在 MySQL/MariaDB 上的数据,我几乎处于可以取得一些良好进展的阶段与项目。我可以通过 SSH 连接到我的数据库,并从 python 脚本检索数据,但我现在希望在 GUI 框中显示该数据。我面临的挑战之一是我有两个单独的脚本来处理连接,一个用于打开,一个用于关闭,我的理论是只有数据访问才需要连接。我已经使用 PyQT5 创建了各种 GUI 和 windows,特别是我希望填充 QtTableWidget。我的脚本目前没有给我任何错误,但它也没有在 table 小部件中显示数据。我的直觉是它没有在打开的连接脚本上正确引用数据库,因此没有要传递的数据,但我正在努力确定有效 google 搜索所需的术语。
我的OpenConn.py如下:
import MySQLdb
from sshtunnel import SSHTunnelForwarder
def Open_Conn():
with SSHTunnelForwarder(
('192.168.0.10', 22),
ssh_password="xxx",
ssh_username="xxx",
remote_bind_address=('localhost', 3306)) as server:
db = MySQLdb.connect(host='localhost',
port=server.local_bind_port,
user='xxx',
passwd='xxx',
db='DBNAME')
cursor = db.cursor()
if __name__ == '__main__':
Open_Conn()
而我的main.py如下:
from PyQt5 import QtCore, QtGui, QtWidgets
import sys
from ViewClientsUI import Ui_ViewClients
from OpenConn import Open_Conn
class ViewClientsWindow(QtWidgets.QDialog, Ui_ViewClients):
def __init__(self):
super(ViewClientsWindow, self).__init__()
self._new_window = None
self.setupUi(self)
def data_load():
with OpenConn.Open_Conn:
connection = OpenConn.Open_Conn()
query = "SELECT * FROM Clients"
result = connection.execute(query)
self.tableWidget.setRowCount(0)
for row_number, row_data in enumerate(result):
self.tableWidget.insertRow(row_number)
for column_number, data in enumerate(row_data):
self.tableWidget.setItem(row_number, column_number, QtWidgets.QTableWidgetItem(str(data)))
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
gui = ViewClientsWindow()
gui.show()
app.exec_()
Open_Conn()
任何人都可以帮助我确定为什么我没有在 table 小部件中获取数据吗?
非常感谢
功能方式:
这种方式显示了您需要设置的功能,以便能够在另一个模块中调用它们。我删除了不能与此功能模式一起使用的上下文管理器,因为它在函数结束时关闭 Open_Conn
。因此 open_conn
函数创建了一个 server
对象和数据库对象 db
,它们将在 close_conn
中被调用以在必要时关闭。
#OpenConn.py
import MySQLdb
from sshtunnel import SSHTunnelForwarder
def open_conn():
server = SSHTunnelForwarder(
('192.168.0.10', 22),
ssh_password="xxx",
ssh_username="xxx",
remote_bind_address=('localhost', 3306))
server.start()
print('opening server : OK')
db = MySQLdb.connect(host='localhost',
port=server.local_bind_port,
user='xxx',
passwd='xxx',
db='DBNAME')
print('opening database : OK')
return (server, db)
def close_conn(server, db):
db.close()
server.stop()
print('closing connection : OK')
from PyQt5 import QtCore, QtGui, QtWidgets
import sys
from ViewClientsUI import Ui_ViewClients
from OpenConn import open_conn, close_conn
class ViewClientsWindow(QtWidgets.QDialog, Ui_ViewClients):
def __init__(self):
super(ViewClientsWindow, self).__init__()
self._new_window = None
self.setupUi(self)
self.data_load()
def data_load(self):
server, db = open_conn()
cursor = db.cursor()
query = "SELECT * FROM Clients"
cursor.execute(query)
results = cursor.fetchall()
self.tableWidget.setRowCount(0)
for row_number, row_data in enumerate(results):
self.tableWidget.insertRow(row_number)
for column_number, data in enumerate(row_data):
self.tableWidget.setItem(row_number, column_number, QtWidgets.QTableWidgetItem(str(data)))
close_conn(server, db)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
gui = ViewClientsWindow()
gui.show()
sys.exit(app.exec_())
上下文管理器方式:
可以通过使用上下文管理器 class 自动处理打开和关闭部分来改进功能模式。管理器可以 return 只有 db.cursor
来执行查询,服务器保留在管理器内部。要获得 cursor
,您可以使用 as 方法 __enter__
中的上下文管理器捕获值 return : with OpenManager() as cursor:
.
要创建它,基本上,您可以在方法 __enter__
中移动 opening 代码(在调用上下文管理器时执行)和 closing 方法 __exit__
内的部分(在 with statement
块的末尾调用)
#OpenConn.py
import MySQLdb
from sshtunnel import SSHTunnelForwarder
class OpenManager(object):
def __init__(self):
self.server =None
self.db = None
# here you could define some parameters and call them next
def __enter__(self):
self.server = SSHTunnelForwarder(
('192.168.0.10', 22),
ssh_password="xxx",
ssh_username="xxx",
remote_bind_address=('localhost', 3306))
self.server.start()
print('opening server : OK')
self.db = MySQLdb.connect(host='localhost',
port=self.server.local_bind_port,
user='xxx',
passwd='xxx',
db='DBNAME')
print('opening database : OK')
return self.db.cursor() #
def __exit__(self, type, value, traceback):
self.db.close()
self.server.stop()
print('closing connection : OK')
此模式允许您在小部件中调用上下文管理器,在 with statement
内,如下所示:
from PyQt5 import QtCore, QtGui, QtWidgets
import sys
from ViewClientsUI import Ui_ViewClients
from OpenConn import OpenManager
class ViewClientsWindow(QtWidgets.QDialog, Ui_ViewClients):
def __init__(self):
super(ViewClientsWindow, self).__init__()
self._new_window = None
self.setupUi(self)
self.data_load()
def data_load(self):
with OpenManager() as cursor:
query = "SELECT * FROM Clients"
cursor.execute(query)
results = cursor.fetchall()
self.tableWidget.setRowCount(0)
for row_number, row_data in enumerate(results):
self.tableWidget.insertRow(row_number)
for column_number, data in enumerate(row_data):
self.tableWidget.setItem(row_number, column_number, QtWidgets.QTableWidgetItem(str(data)))
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
gui = ViewClientsWindow()
gui.show()
sys.exit(app.exec_())
您也可以直接在小部件中创建与 SSHTunnelForwarder
的连接以避免这种情况,并使用 class 提供的上下文管理器,然后在其中创建数据库连接。
上面显示的自定义 class 只是一种在一个上下文中混合与服务器和数据库的连接的方法,以便在您的代码中的许多地方需要这些连接时变得容易。
我正在深入学习 Python,同时尝试制作一个应用程序,使用存储在 MySQL/MariaDB 上的数据,我几乎处于可以取得一些良好进展的阶段与项目。我可以通过 SSH 连接到我的数据库,并从 python 脚本检索数据,但我现在希望在 GUI 框中显示该数据。我面临的挑战之一是我有两个单独的脚本来处理连接,一个用于打开,一个用于关闭,我的理论是只有数据访问才需要连接。我已经使用 PyQT5 创建了各种 GUI 和 windows,特别是我希望填充 QtTableWidget。我的脚本目前没有给我任何错误,但它也没有在 table 小部件中显示数据。我的直觉是它没有在打开的连接脚本上正确引用数据库,因此没有要传递的数据,但我正在努力确定有效 google 搜索所需的术语。
我的OpenConn.py如下:
import MySQLdb
from sshtunnel import SSHTunnelForwarder
def Open_Conn():
with SSHTunnelForwarder(
('192.168.0.10', 22),
ssh_password="xxx",
ssh_username="xxx",
remote_bind_address=('localhost', 3306)) as server:
db = MySQLdb.connect(host='localhost',
port=server.local_bind_port,
user='xxx',
passwd='xxx',
db='DBNAME')
cursor = db.cursor()
if __name__ == '__main__':
Open_Conn()
而我的main.py如下:
from PyQt5 import QtCore, QtGui, QtWidgets
import sys
from ViewClientsUI import Ui_ViewClients
from OpenConn import Open_Conn
class ViewClientsWindow(QtWidgets.QDialog, Ui_ViewClients):
def __init__(self):
super(ViewClientsWindow, self).__init__()
self._new_window = None
self.setupUi(self)
def data_load():
with OpenConn.Open_Conn:
connection = OpenConn.Open_Conn()
query = "SELECT * FROM Clients"
result = connection.execute(query)
self.tableWidget.setRowCount(0)
for row_number, row_data in enumerate(result):
self.tableWidget.insertRow(row_number)
for column_number, data in enumerate(row_data):
self.tableWidget.setItem(row_number, column_number, QtWidgets.QTableWidgetItem(str(data)))
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
gui = ViewClientsWindow()
gui.show()
app.exec_()
Open_Conn()
任何人都可以帮助我确定为什么我没有在 table 小部件中获取数据吗? 非常感谢
功能方式:
这种方式显示了您需要设置的功能,以便能够在另一个模块中调用它们。我删除了不能与此功能模式一起使用的上下文管理器,因为它在函数结束时关闭 Open_Conn
。因此 open_conn
函数创建了一个 server
对象和数据库对象 db
,它们将在 close_conn
中被调用以在必要时关闭。
#OpenConn.py
import MySQLdb
from sshtunnel import SSHTunnelForwarder
def open_conn():
server = SSHTunnelForwarder(
('192.168.0.10', 22),
ssh_password="xxx",
ssh_username="xxx",
remote_bind_address=('localhost', 3306))
server.start()
print('opening server : OK')
db = MySQLdb.connect(host='localhost',
port=server.local_bind_port,
user='xxx',
passwd='xxx',
db='DBNAME')
print('opening database : OK')
return (server, db)
def close_conn(server, db):
db.close()
server.stop()
print('closing connection : OK')
from PyQt5 import QtCore, QtGui, QtWidgets
import sys
from ViewClientsUI import Ui_ViewClients
from OpenConn import open_conn, close_conn
class ViewClientsWindow(QtWidgets.QDialog, Ui_ViewClients):
def __init__(self):
super(ViewClientsWindow, self).__init__()
self._new_window = None
self.setupUi(self)
self.data_load()
def data_load(self):
server, db = open_conn()
cursor = db.cursor()
query = "SELECT * FROM Clients"
cursor.execute(query)
results = cursor.fetchall()
self.tableWidget.setRowCount(0)
for row_number, row_data in enumerate(results):
self.tableWidget.insertRow(row_number)
for column_number, data in enumerate(row_data):
self.tableWidget.setItem(row_number, column_number, QtWidgets.QTableWidgetItem(str(data)))
close_conn(server, db)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
gui = ViewClientsWindow()
gui.show()
sys.exit(app.exec_())
上下文管理器方式:
可以通过使用上下文管理器 class 自动处理打开和关闭部分来改进功能模式。管理器可以 return 只有 db.cursor
来执行查询,服务器保留在管理器内部。要获得 cursor
,您可以使用 as 方法 __enter__
中的上下文管理器捕获值 return : with OpenManager() as cursor:
.
要创建它,基本上,您可以在方法 __enter__
中移动 opening 代码(在调用上下文管理器时执行)和 closing 方法 __exit__
内的部分(在 with statement
块的末尾调用)
#OpenConn.py
import MySQLdb
from sshtunnel import SSHTunnelForwarder
class OpenManager(object):
def __init__(self):
self.server =None
self.db = None
# here you could define some parameters and call them next
def __enter__(self):
self.server = SSHTunnelForwarder(
('192.168.0.10', 22),
ssh_password="xxx",
ssh_username="xxx",
remote_bind_address=('localhost', 3306))
self.server.start()
print('opening server : OK')
self.db = MySQLdb.connect(host='localhost',
port=self.server.local_bind_port,
user='xxx',
passwd='xxx',
db='DBNAME')
print('opening database : OK')
return self.db.cursor() #
def __exit__(self, type, value, traceback):
self.db.close()
self.server.stop()
print('closing connection : OK')
此模式允许您在小部件中调用上下文管理器,在 with statement
内,如下所示:
from PyQt5 import QtCore, QtGui, QtWidgets
import sys
from ViewClientsUI import Ui_ViewClients
from OpenConn import OpenManager
class ViewClientsWindow(QtWidgets.QDialog, Ui_ViewClients):
def __init__(self):
super(ViewClientsWindow, self).__init__()
self._new_window = None
self.setupUi(self)
self.data_load()
def data_load(self):
with OpenManager() as cursor:
query = "SELECT * FROM Clients"
cursor.execute(query)
results = cursor.fetchall()
self.tableWidget.setRowCount(0)
for row_number, row_data in enumerate(results):
self.tableWidget.insertRow(row_number)
for column_number, data in enumerate(row_data):
self.tableWidget.setItem(row_number, column_number, QtWidgets.QTableWidgetItem(str(data)))
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
gui = ViewClientsWindow()
gui.show()
sys.exit(app.exec_())
您也可以直接在小部件中创建与 SSHTunnelForwarder
的连接以避免这种情况,并使用 class 提供的上下文管理器,然后在其中创建数据库连接。
上面显示的自定义 class 只是一种在一个上下文中混合与服务器和数据库的连接的方法,以便在您的代码中的许多地方需要这些连接时变得容易。