Tabla de contenido
4 operaciones de base de datos
4.1 Conectarse a la base de datos
4.2 Ejecutar consultas SQL y actualizaciones:
4.3 Mostrar datos usando modelos y vistas
5.1 Conceptos y ventajas de la programación multiproceso
5.2 Usando subprocesos múltiples en PyQt
5.3 Manejo de problemas de sincronización y comunicación entre múltiples subprocesos
5.3.1 Mecanismo de ranura de señal
5.3.2 Acceso a datos seguro para subprocesos
Guía de columna
Dirección de suscripción de columna: https://blog.csdn.net/qq_35831906/category_12375510.html
4 operaciones de base de datos
Las operaciones de bases de datos en PyQt6 involucran principalmente el módulo SQL de Qt, que proporciona funciones para conectar y administrar bases de datos. La siguiente es una descripción general de las operaciones de la base de datos PyQt6:
Conexiones de bases de datos: utilice
QSqlDatabase
clases para establecer conexiones a bases de datos. Puede conectarse a varios motores de bases de datos, como SQLite, MySQL, PostgreSQL, etc. La conexión debe especificar el tipo de base de datos, el host, el nombre de usuario, la contraseña y otra información.Consulta de base de datos: utilice
QSqlQuery
clases para ejecutar declaraciones de consulta SQL, como SELECT, INSERT, UPDATE, etc. Los resultados de la consulta se pueden obtener mediante iteración.Arquitectura de vista de modelo: PyQt6 proporciona
QSqlTableModel
otrasQSqlQueryModel
clases de modelo para conectar datos de la base de datos con las clases de vista de Qt (como QTableView). Esto facilita la visualización y edición de datos en la base de datos en una vista tabular.Gestión de transacciones: puede utilizar
QSqlDatabase.transaction()
yQSqlDatabase.commit()
para gestionar las transacciones de la base de datos para garantizar la coherencia e integridad de los datos.Enlace de datos: mediante
bindValue()
métodos puede vincular variables a consultas SQL, lo que ayuda a prevenir ataques de inyección SQL.Manejo de errores: pueden ocurrir errores en las operaciones de la base de datos y se puede obtener información detallada sobre los errores
QSqlQuery
marcando .lastError()
4.1 Conectarse a la base de datos
Utilice la clase QSqlDatabase de Qt para conectarse a una base de datos. Aquí hay un ejemplo simple:
from PyQt6.QtSql import QSqlDatabase
db = QSqlDatabase.addDatabase("QSQLITE")
db.setDatabaseName("my_database.db")
if db.open():
print("Connected to database")
else:
print("Failed to connect")
4.2 Ejecutar consultas SQL y actualizaciones:
Puede utilizar la clase QSqlQuery para realizar consultas SQL y operaciones de actualización. Aquí hay un ejemplo:
from PyQt6.QtSql import QSqlQuery
query = QSqlQuery()
query.exec("SELECT * FROM employees")
while query.next():
name = query.value("name")
print("Employee name:", name)
4.3 Mostrar datos usando modelos y vistas
Qt proporciona una arquitectura de vista de modelo para mostrar datos de una base de datos. Por ejemplo, puede utilizar QSqlTableModel para mostrar datos en un QTableView. Aquí hay un ejemplo:
import sys
from PyQt6.QtWidgets import QApplication, QMainWindow, QTableView, QVBoxLayout, QWidget, QPushButton, QLineEdit, QDockWidget
from PyQt6.QtSql import QSqlDatabase, QSqlTableModel, QSqlQuery
from PyQt6.QtCore import Qt
class AddDataDialog(QWidget):
def __init__(self, model):
super().__init__()
self.model = model
layout = QVBoxLayout()
self.setLayout(layout)
# 添加姓名输入框
self.name_input = QLineEdit(self)
layout.addWidget(self.name_input)
# 添加职位输入框
self.position_input = QLineEdit(self)
layout.addWidget(self.position_input)
# 添加 "Add Data" 按钮,并连接到添加数据函数
add_button = QPushButton("Add Data", self)
add_button.clicked.connect(self.add_data)
layout.addWidget(add_button)
def add_data(self):
# 获取姓名和职位输入框的内容
name = self.name_input.text()
position = self.position_input.text()
# 准备插入数据的SQL查询
query = QSqlQuery()
query.prepare("INSERT INTO employees (name, position) VALUES (?, ?)")
query.bindValue(0, name)
query.bindValue(1, position)
if query.exec():
print("Data added successfully")
self.model.select() # 刷新表格数据
else:
print("Error adding data:", query.lastError().text())
def create_database_connection():
# 创建数据库连接
db = QSqlDatabase.addDatabase("QSQLITE")
db.setDatabaseName("employees.db")
if not db.open():
print("Error: Could not open database.")
return None
return db
def create_table(db):
# 创建表格的SQL查询
query = QSqlQuery()
query.exec("CREATE TABLE IF NOT EXISTS employees (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, position TEXT)")
def setup_model(db):
# 设置数据库表格模型
model = QSqlTableModel()
model.setTable("employees")
model.setEditStrategy(QSqlTableModel.EditStrategy.OnManualSubmit) # 手动提交更改
model.select()
return model
if __name__ == "__main__":
app = QApplication(sys.argv)
db = create_database_connection()
if not db:
sys.exit(1)
create_table(db)
model = setup_model(db)
view = QTableView()
view.setModel(model)
add_data_dialog = AddDataDialog(model)
window = QMainWindow()
window.setWindowTitle("Database Table Example")
window.setCentralWidget(view)
window.setGeometry(100, 100, 800, 600)
add_data_button = QPushButton("Add Data", window)
add_data_button.clicked.connect(add_data_dialog.show)
# 创建 DockWidget 并添加到主窗口的右侧停靠区
dock_widget = QDockWidget("Add Data", window)
dock_widget.setWidget(add_data_dialog)
window.addDockWidget(Qt.DockWidgetArea.RightDockWidgetArea, dock_widget)
window.show()
sys.exit(app.exec())
5 programación multiproceso
5.1 Conceptos y ventajas de la programación multiproceso
La programación multiproceso en PyQt6 le permite ejecutar múltiples tareas simultáneamente en su aplicación para mejorar el rendimiento, la capacidad de respuesta y la utilización de recursos. Cuando utilice subprocesos múltiples, debe prestar atención a la sincronización y la comunicación entre subprocesos para evitar carreras de datos y otros problemas de concurrencia. La siguiente es una descripción general de la programación multiproceso de PyQt6:
Clase de subproceso (QThread):
QThread
es la clase base de subproceso proporcionada por PyQt6, que se utiliza para crear y administrar subprocesos. Puede heredarQThread
e implementarrun()
el método para definir la lógica de ejecución del hilo.Seguridad de subprocesos: en un entorno multiproceso, varios subprocesos pueden acceder y modificar recursos compartidos simultáneamente. Es importante garantizar que el acceso a los recursos compartidos sea seguro para subprocesos y que se
QMutex
puedan utilizar mutex ( ) para controlar el acceso a los recursos compartidos.Mecanismo de señal y ranura: en subprocesos múltiples, generalmente no es posible actualizar la interfaz de usuario directamente en un subproceso no principal. Puede utilizar el mecanismo de señal y ranura para actualizar la interfaz procesando la señal en el hilo principal, evitando así el problema de actualización de la interfaz entre hilos.
Escenarios de aplicación de subprocesos múltiples: el subproceso múltiple es especialmente útil en las siguientes situaciones:
- Realice operaciones que requieren mucho tiempo, como lectura y escritura de archivos, solicitudes de red, etc., para evitar bloquear el hilo principal.
- Realice una actualización de datos en tiempo real, como datos de sensores, datos de gráficos, etc.
- Procese múltiples tareas simultáneamente para mejorar el rendimiento general del programa.
Sincronización y comunicación de subprocesos: la programación multiproceso debe considerar la sincronización y la comunicación entre subprocesos. Los mecanismos de sincronización apropiados (como mutex, semáforos, variables de condición, etc.) y mecanismos de comunicación (como colas, ranuras de señal, etc.) pueden garantizar la cooperación correcta entre subprocesos.
Evite el punto muerto y la falta de subprocesos: el punto muerto y la falta de subprocesos son problemas comunes en la programación multiproceso. Asegúrese de diseñar y organizar correctamente la sincronización y comunicación de subprocesos para evitar estos problemas.
En resumen, la programación multiproceso puede mejorar significativamente el rendimiento y la capacidad de respuesta de su aplicación, pero también requiere una cuidadosa consideración de la seguridad de los subprocesos y los mecanismos de sincronización adecuados. PyQt6 proporciona algunas clases y herramientas para ayudarle a implementar aplicaciones multiproceso, pero los posibles problemas de concurrencia deben manejarse con cuidado.
5.2 Usando subprocesos múltiples en PyQt
En PyQt, puede utilizar la clase QThread para crear y administrar subprocesos. A continuación se muestra un ejemplo que muestra cómo ejecutar una tarea que requiere mucho tiempo en un hilo:
from PyQt6.QtCore import QThread, pyqtSignal
class WorkerThread(QThread):
result_ready = pyqtSignal(str)
def run(self):
# 执行耗时任务
result = "Task result"
self.result_ready.emit(result)
thread = WorkerThread()
thread.result_ready.connect(lambda result: print("Result:", result))
thread.start()
5.3 Manejo de problemas de sincronización y comunicación entre múltiples subprocesos
En la programación multiproceso, es fundamental abordar los problemas de sincronización y comunicación entre subprocesos para garantizar la coherencia de los datos y la estabilidad de la aplicación. PyQt proporciona varios mecanismos para ayudar con estos problemas, los más importantes de los cuales son el mecanismo de ranuras de señales y el acceso a datos seguro para subprocesos.
5.3.1 Mecanismo de ranura de señal
El mecanismo de ranura de señal es una herramienta importante en PyQt para la comunicación entre subprocesos. Permite que un objeto (el remitente de la señal) emita una señal y otro objeto (el receptor de la función de ranura) conecte la señal a la función de ranura para realizar la acción correspondiente cuando se dispara la señal. Esto es especialmente útil en un entorno de subprocesos múltiples, ya que evita el intercambio directo de datos entre subprocesos.
El siguiente es un ejemplo sencillo que demuestra cómo utilizar el mecanismo de ranura de señal en subprocesos múltiples:
import sys
from PyQt6.QtCore import QThread, pyqtSignal
from PyQt6.QtWidgets import QApplication, QMainWindow, QPushButton
class WorkerThread(QThread):
result_ready = pyqtSignal(str)
def run(self):
result = "Task result"
self.result_ready.emit(result)
class MyWindow(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("Thread Communication Example")
self.setGeometry(100, 100, 400, 300)
self.button = QPushButton("Start Task", self)
self.button.setGeometry(150, 150, 100, 30)
self.button.clicked.connect(self.start_thread)
def start_thread(self):
self.thread = WorkerThread()
self.thread.result_ready.connect(self.handle_result)
self.thread.start()
def handle_result(self, result):
print("Result:", result)
if __name__ == "__main__":
app = QApplication(sys.argv)
window = MyWindow()
window.show()
sys.exit(app.exec())
5.3.2 Acceso a datos seguro para subprocesos
Es probable que se produzcan condiciones de carrera e inconsistencias de datos cuando varios subprocesos acceden a datos compartidos al mismo tiempo. Para evitar estos problemas, es necesario utilizar bloqueos de exclusión mutua (mutex) para proteger el acceso a los datos compartidos. QMutex y QMutexLocker en PyQt pueden ayudarlo a lograr un acceso a datos seguro para subprocesos.
A continuación se muestra un ejemplo sencillo que muestra cómo acceder de forma segura a datos compartidos en varios subprocesos:
import sys
from PyQt6.QtCore import QThread, QMutex, QMutexLocker
class SharedData:
def __init__(self):
self.mutex = QMutex() # 用于保护共享数据的互斥锁
self.data = 0
def increment(self):
locker = QMutexLocker(self.mutex) # 加锁
self.data += 1
class WorkerThread(QThread):
def __init__(self, shared_data):
super().__init__()
self.shared_data = shared_data
def run(self):
for _ in range(10):
self.shared_data.increment()
if __name__ == "__main__":
shared_data = SharedData() # 创建共享数据对象
threads = [WorkerThread(shared_data) for _ in range(4)] # 创建多个工作线程
for thread in threads:
thread.start() # 启动工作线程
for thread in threads:
thread.wait() # 等待所有工作线程完成
print("Shared data:", shared_data.data) # 打印最终共享数据的值
producción:
En este ejemplo, cada subproceso de trabajo realiza 10 incrementos en un bucle, utilizando un mutex para garantizar que solo un subproceso pueda acceder y modificar las propiedades
SharedData
del objetodata
en cualquier momento. Esto evita carreras de datos e inconsistencias.Tenga en cuenta que este ejemplo utiliza subprocesos múltiples y mutex en Python, que son ligeramente diferentes de los subprocesos y mutex en Qt.
PyQt6.QtCore
Asegúrese de que tanto la biblioteca Qt como el soporte de subprocesos de Python (por ejemplo , una biblioteca) existan en su entornothreading
para que el código pueda ejecutarse correctamente.
5.4 Evitar interbloqueos y falta de subprocesos
Evitar el punto muerto y la falta de subprocesos es una cuestión clave en la programación multiproceso. El punto muerto se refiere a varios subprocesos que esperan entre sí para liberar el bloqueo, lo que impide que el programa continúe ejecutándose. La falta de subprocesos significa que un subproceso no puede obtener los recursos requeridos o se bloquea durante mucho tiempo, lo que hace que otros subprocesos ocupen recursos y el subproceso no pueda continuar ejecutándose. Las siguientes son explicaciones detalladas y ejemplos de cómo evitar interbloqueos y falta de subprocesos en PyQt6:
Evite los puntos muertos:
Adquisición de bloqueos ordenados: cuando varios subprocesos necesitan adquirir varios bloqueos, asegúrese de que los adquieran en el mismo orden, lo que puede reducir el riesgo de interbloqueo.
Mecanismo de tiempo de espera: utilice un mecanismo de tiempo de espera al adquirir un candado. Si el candado no se puede adquirir dentro de un cierto período de tiempo, abandone y libere el candado existente.
Evite la falta de hilo:
Equidad: utilice bloqueos justos y estrategias de asignación de recursos para garantizar que todos los subprocesos tengan las mismas oportunidades de obtener recursos y evitar que un subproceso no pueda obtener los recursos necesarios durante mucho tiempo.
Prioridad: en algunos casos, puede establecer diferentes prioridades para los subprocesos para garantizar que los subprocesos de alta prioridad no puedan obtener recursos durante mucho tiempo.
Aquí hay un ejemplo simple que muestra cómo usar QMutex en PyQt6 para evitar interbloqueos y falta de subprocesos:
import sys
from PyQt6.QtCore import QThread, QMutex, QMutexLocker
# 共享资源类,用于展示互斥锁的使用来避免死锁和线程饥饿
class SharedResource:
def __init__(self):
self.mutex1 = QMutex() # 第一个互斥锁
self.mutex2 = QMutex() # 第二个互斥锁
def process1(self):
with QMutexLocker(self.mutex1): # 获取第一个锁
print("Process 1: Mutex 1 locked")
QThread.msleep(100) # 模拟处理时间
with QMutexLocker(self.mutex2): # 获取第二个锁
print("Process 1: Mutex 2 locked")
def process2(self):
with QMutexLocker(self.mutex2): # 获取第二个锁
print("Process 2: Mutex 2 locked")
QThread.msleep(100) # 模拟处理时间
with QMutexLocker(self.mutex1): # 获取第一个锁
print("Process 2: Mutex 1 locked")
class WorkerThread(QThread):
def __init__(self, shared_resource, process_func):
super().__init__()
self.shared_resource = shared_resource
self.process_func = process_func
def run(self):
self.process_func()
if __name__ == "__main__":
shared_resource = SharedResource()
thread1 = WorkerThread(shared_resource, shared_resource.process1)
thread2 = WorkerThread(shared_resource, shared_resource.process2)
thread1.start() # 启动线程1
thread2.start() # 启动线程2
thread1.wait() # 等待线程1完成
thread2.wait() # 等待线程2完成
print("Main thread exited") # 主线程退出
En este ejemplo, dos subprocesos intentan adquirir dos bloqueos diferentes (mutex1 y mutex2). Los interbloqueos se evitan adquiriendo siempre los bloqueos en el mismo orden. Al mismo tiempo, al utilizar QMutexLocker al adquirir el bloqueo, puede asegurarse de que el hilo libere el bloqueo cuando salga del alcance.
Cabe señalar que el punto muerto y la falta de subprocesos son problemas complejos que pueden surgir en escenarios más complejos. Evitar el estancamiento y la falta de subprocesos requiere un diseño y pruebas cuidadosos para garantizar que los subprocesos estén sincronizados y coordinados adecuadamente cuando trabajan juntos.
QMutex
yQMutexLocker
QMutex
yQMutexLocker
son dos clases importantes para la sincronización de subprocesos en PyQt. Ayudan a garantizar la sincronización adecuada de múltiples subprocesos que acceden a recursos compartidos para evitar condiciones de carrera e inconsistencias de datos. Aquí tienes explicaciones y ejemplos sobre ellos:
QMutex (bloqueo de exclusión mutua): un bloqueo de exclusión mutua es un mecanismo de sincronización de subprocesos que se utiliza para controlar el acceso a recursos compartidos por parte de múltiples subprocesos. En un entorno multiproceso, un subproceso puede tomar posesión de un mutex, lo que permite un acceso seguro a un recurso compartido. Otros subprocesos deben esperar antes de adquirir el mutex para garantizar que solo un subproceso pueda acceder al recurso compartido a la vez.
Código de muestra:
from PyQt6.QtCore import QMutex
mutex = QMutex()
def thread_function():
mutex.lock()
# 访问共享资源
mutex.unlock()
# 创建多个线程,每个线程执行 thread_function
QMutexLocker (casillero de exclusión mutua): QMutexLocker
es QMutex
una clase auxiliar de, se bloquea automáticamente cuando se crea QMutex
y libera el bloqueo cuando se destruye. Esto puede garantizar que, dentro de un alcance, el subproceso pueda liberar correctamente el bloqueo después de adquirirlo, evitando así el punto muerto causado por olvidarse de liberar el bloqueo.
Código de muestra:
from PyQt6.QtCore import QMutex, QMutexLocker
mutex = QMutex()
def thread_function():
with QMutexLocker(mutex): # 进入作用域时自动锁定,离开作用域时自动释放
# 访问共享资源
# 创建多个线程,每个线程执行 thread_function
Cuando se usa
QMutexLocker
, el bloqueo se libera automáticamente cuando el hilo sale del alcance (por ejemplo, usandowith
la declaración), independientemente de si ocurre una excepción.