python mysqlconnection' object is not callable

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MariaDB/MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
edem
User
Beiträge: 2
Registriert: Sonntag 16. Februar 2025, 15:10

Hallo Zusammen,
ich habe ein Problem mit der Verbindung der MYSQL-Datenbank und Python.
Der connection-string steh in einer connection.ini und funktioniert auch.
Die einzelnen Funktionen sind: load_data, edit_data, save_data, delete_data, import_data, export_data und Programm beenden.
Über load_data wird die connection ausgeführt und die Tabelle wird geladen.
Wenn ich einen Datensatz einfüge oder auch lösche, dann passiert das auch im Hintergrund, doch jeweils mit der Meldung: python mysqlconnection' object is not callable
hier der Code:
import os
import sys
from PySide6.QtCore import *
from PySide6.QtGui import *
from PySide6.QtWidgets import *
import pandas as pd
import mysql.connector
import csv
from ui_frm_main import Ui_frm_main

class MainWindow(QMainWindow, Ui_frm_main):
def __init__(self):
super(MainWindow, self).__init__()
self.setupUi(self)

# Set up the status bar
self.status_bar = QStatusBar()
self.setStatusBar(self.status_bar)

# Verbinden der Buttons mit ihren Funktionen
self.btn_load.clicked.connect(self.load_data)
self.btn_insert.clicked.connect(self.insert_data)
self.btn_edit.clicked.connect(self.edit_data)
self.btn_save.clicked.connect(self.save_data)
self.btn_import.clicked.connect(self.import_data)
self.btn_delete.clicked.connect(self.delete_data)
self.btn_export.clicked.connect(self.export_csv)
self.btn_beenden.clicked.connect(self.close)
self.inp_suchfeld.textChanged.connect(self.search_data)
self.checkBox.stateChanged.connect(self.toggle_buttons)

# Schreibschutz aktivieren/deaktivieren
def toggle_buttons(self):
# Überprüfe den Zustand der Checkbox
if self.checkBox.isChecked():
self.btn_insert.setEnabled(False)
self.btn_edit.setEnabled(False)
self.btn_save.setEnabled(False)
self.btn_delete.setEnabled(False)
self.btn_import.setEnabled(False)
else:
self.btn_insert.setEnabled(True)
self.btn_edit.setEnabled(True)
self.btn_save.setEnabled(True)
self.btn_delete.setEnabled(True)
self.btn_import.setEnabled(True)

# Datenbankverbindung herstellen *******************************************************************

def db_connection(self):
config_dir = os.path.dirname((os.path.abspath(__file__)))
connection_file = os.path.join(config_dir, 'connection.ini')
try:
self.db_connection = mysql.connector.connect(option_files=connection_file)
if self.db_connection.is_connected():
self.lbl_meldungen.setText("Verbindung zur Mysql-Datenbank OK!")
self.cursor = self.db_connection.cursor()
return self.db_connection
except mysql.connector.Error as e:
self.lbl_meldungen.setText("Fehler Datenbankverbindung.", e)
return config_dir
#self.load_data()

# Daten aus Datenbank laden *********************************************************************************

def load_data(self):
try:
self.db_connection()
self.cursor = self.db_connection.cursor()
self.cursor.execute("SELECT * FROM zaehlerdaten")
result = self.cursor.fetchall()
self.tbl_zaehler.setRowCount(0)
for row_number, row_data in enumerate(result):
self.tbl_zaehler.insertRow(row_number)
for column_number, data in enumerate(row_data):
self.tbl_zaehler.setItem(row_number, column_number, QTableWidgetItem(str(data)))
self.lbl_meldungen.setText("Daten erfolgreich geladen.")
self.display_record_count()
return
except Exception as e:
self.lbl_meldungen.setText(f"Fehler beim Laden der Daten: {str(e)}")

# Daten nach CSV Exportieren ***************************************************************************
def export_csv(self):
# if not row_data:
# QMessageBox.warning(self, 'Input Error', 'Please enter some data to save.')
# return

# Dateidialog, wo die CSV gespeichert wird*******************************************************
file_path, _ = QFileDialog.getSaveFileName(self, 'Save CSV File', '', 'CSV Files (*.csv)')
if not file_path:
return # Benutzer bricht ab******************************
# Kopfzeilen für die Exportdatei********************************
headers = ['idzaehler', 'zaehlerguid', 'zaehlergruppe', 'zaehlerinhaber', 'zaehlerbatiment', 'zaehlerlokal',
'zaehlername', 'zaehlerdescription', 'zaehleraiwrite', 'zaehlermodul', 'zaehleripAdresse',
'zaehlercode', 'zaehlerinstanz', 'zaehlertype', 'zaehlereinheit', 'zaehlereinbaudatum']
try:
with open(file_path, mode='w', newline='', encoding='utf-8') as file:
writer = csv.writer(file)
writer.writerow(headers)
for row in range(self.tbl_zaehler.rowCount()):
row_data = []
for column in range(self.tbl_zaehler.columnCount()):
item = self.tbl_zaehler.item(row, column)
if item:
row_data.append(item.text())
else:
row_data.append('')
writer.writerow(row_data)
self.lbl_meldungen.setText("Daten erfolgreich nach CSV exportiert.")
except Exception as e:
self.lbl_meldungen.setText(f"Fehler beim Exportieren der Daten: {str(e)}")

# CSV Daten importieren *************************************************************************************
def import_data(self):
self.cursor = self.db_connection.cursor()
self.lbl_meldungen.setText("Neue Daten importieren...")
# CSV-Datei auswählen***********************************************************
options = QFileDialog.Options()
file_name, _ = QFileDialog.getOpenFileName(self, "CSV Datei auswählen", "", "CSV Dateien (*.csv);;Alle Dateien (*)", options=options)
if file_name:
try:
data = pd.read_csv(file_name)
for index, row in data.iterrows():
query = "INSERT INTO zaehlerdaten (idzaehler, zaehlerguid, zaehlergruppe, zaehlerinhaber, zaehlerbatiment, zaehlerlokal, zaehlername, zaehlerdescription, zaehleraiwrite, zaehlermodul, zaehleripadresse, zaehlercode, zaehlerinstanz, zaehlertype, zaehlereinheit, zaehlereinbaudatum) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)"
self.cursor.execute(query, tuple(row))
self.db_connection.commit()
QMessageBox.information(self, "Erfolg", "CSV-Daten erfolgreich importiert!")
self.tbl_zaehler.clear()
self.load_data()
except Exception as e:
QMessageBox.critical(self, "Fehler", f"Fehler beim Importieren der CSV-Daten: {e}")

# Daten bearbeiten ********************************************************************
def edit_data(self):
try:
self.load_data
self.cursor = self.db_connection.cursor()
self.lbl_meldungen.setText("Daten bearbeiten...")
self.cursor.execute("SELECT * FROM zaehlerdaten")
rows = self.cursor.fetchall()
self.tbl_zaehler.setRowCount(len(rows))
self.tbl_zaehler.setColumnCount(len(rows[0]))
self.tbl_zaehler.setHorizontalHeaderLabels([i[0] for i in self.cursor.description])
for row_idx, row in enumerate(rows):
for col_idx, item in enumerate(row):
self.tbl_zaehler.setItem(row_idx, col_idx, QTableWidgetItem(str(item)))
except mysql.connector.Error as e:
QMessageBox.critical(self, "Database Error", f"Error: {e}")

def save_data(self):
try:
self.cursor = self.db_connection.cursor()
self.lbl_meldungen.setText("Daten bearbeiten...")
for row in range(self.tbl_zaehler.rowCount()):
row_data = []
for col in range(self.tbl_zaehler.columnCount()):
item = self.tbl_zaehler.item(row, col)
row_data.append(item.text() if item else "")
update_query = f"UPDATE zaehlerdaten SET idzaehler = %s, zaehlerguid = %s, zaehlergruppe = %s, zaehlerinhaber = %s, zaehlerbatiment = %s, zaehlerlokal = %s, zaehlername = %s, zaehlerdescription = %s, zaehleraiwrite = %s, zaehlermodul = %s, zaehleripadresse = %s, zaehlercode = %s, zaehlerinstanz = %s, zaehlertype = %s, zaehlereinheit = %s, zaehlereinbaudatum = %s WHERE id = %s"
self.cursor.execute(update_query, row_data)
self.db_connection.commit()
self.cursor.close()
self.db_connection.close()
self.tbl_zaehler.clear()
self.load_data()
self.lbl_meldungen.setText("Daten wurden gespeichert!")
except mysql.connector.Error as e:
QMessageBox.critical(self, "Datenbank Fehler", f"Error: {e}")


usw.
ich bin leider ein Anfänger und habe nicht die Erfahrung in Python, deshalb auch bitte die Nachsicht mit dem import mit *
denke das Problem liegt in der connection öffnen und schließen.
Hat vielleicht einer oder eine ein paar tipps wie ich das Problem lösen, bzw. umgehen kann?
Vielen Dank im Voraus.
Benutzeravatar
sparrow
User
Beiträge: 4501
Registriert: Freitag 17. April 2009, 10:28

Wenn du schon weißt, dass *-Importe scheiße sind, warum verwendest du sie dann trotzdem? Das hat nichts damit zu tun, Anfänger zu sein.

Du fängst blind alle Exceptions und gibst dann eine wenig hilfreiche Fehlermeldung aus. Würdest du das nicht tun, wüsstest du wo der Fehler auftritt und müsstest nicht raten.
Und wenn du das so lösen willst, dann gib wenigstens den Traceback aus.
Sirius3
User
Beiträge: 18216
Registriert: Sonntag 21. Oktober 2012, 17:20

Eingerückt wird immer mit 4 Leerzeichen pro Ebene, nicht mal 4 und mal 8.
*-Importe benutzt man nicht. Man generiert aus den ui-Dateien keine Python-Dateien, sondern lädt die ui-Dateien direkt. Statt os.path benutzt man heutzutage pathlib.Path.

Du hast eine Methode `db_connection`, die ein Attribut `db_connection` setzt. Damit überdeckst Du die Methode, was auch zu dem Fehler führt. Deshalb darf man nachträgich keine Attribute mehr einführen, alle Attribute sollten schon in __init__ gesetzt werden.
Der Rückgabewert der Methode ist auch fehlerhaft. Einmal lieferst Du eine DB-Connection und einmal einen String zurück und mal auch None. Methoden sollten aber immer den selben Typ zurückliefern.
Cursor sind etwas kurzlebiges, und sollten nicht Attribute sein.
Wie *-Importe sind auch * bei SELECT schlecht, weil man die Reihenfolge der Felder nicht kennt.
Bei jeder Zelle setzt Du einmal lbl_meldungen. Das ist deutlich zu oft.
Wenn Du pandas nur dazu benutzt, um einmal ein CSV-Datei zu laden, dann ist das ziemlich übertrieben, zum Schreiben nimmst Du ja auch das csv-Modul.
edem
User
Beiträge: 2
Registriert: Sonntag 16. Februar 2025, 15:10

Oha, ich fühle mich echt erschlagen, aus Beispielen, die ich mir angeschaut habe und versucht habe das zu verstehen, habe ich das nachgebaut aber anscheinend läuft das total aus der Norm.
Das heißt also erstmal alle Exceptions rausschmeissen, die Sternchen vergessen, den select-import mit Feldern eingeben, .........
Ich werde mein Glück versuchen, danke schon mal für die ganze Reihe an Hinweisen.
Antworten