Abfrage an einen OPCUA Server

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Knausbär
User
Beiträge: 9
Registriert: Mittwoch 15. September 2021, 12:08

Hallo,

ich habe ein Python Programm geschrieben was sich mittels eines OPCUA Clients mit einer Siemens Steuerung (1515F) verbindet und relativ viele Daten abfragen muss.

Nun Frage ich von einem Datenbaustein alle Daten einzeln ab. Dies dauert aber für einen Durchlauf in meinem Programm ca 30 Sekunden.

Ich muss jede Minute von der Steuerung gut 1000 Daten abfragen. Zur Zeit sieht meine Abfrage so aus. Oder ist das zu umständlich :?

Code: Alles auswählen

if Sensoren_Kr > 0:
			for sensKr in range(0, Sensoren_Kr):			
				sens1 = str(sensKr)
				minimumKr, minimumKrReal = leseWert('ns=3;s="Daten_Raspberry"."Pufferspeicher_Sensorwerte"."Puffer"[%s]."Kran"."Sekunde"[%s]."Sensor"[%s]."minimum"' % (PufferStr, sek1, sens1)) 
				mittelKr, mittelKrReal = leseWert('ns=3;s="Daten_Raspberry"."Pufferspeicher_Sensorwerte"."Puffer"[%s]."Kran"."Sekunde"[%s]."Sensor"[%s]."mittel"' % (PufferStr, sek1, sens1)) 
				maximumKr, maximumKrReal = leseWert('ns=3;s="Daten_Raspberry"."Pufferspeicher_Sensorwerte"."Puffer"[%s]."Kran"."Sekunde"[%s]."Sensor"[%s]."maximum"' % (PufferStr, sek1, sens1))

				minimumKrListe.append(round(minimumKr, 3))
				mittelKrListe.append(round(mittelKr, 3))
				maximumKrListe.append(round(maximumKr, 3))
				
				minimumKrTemp, minimumKrTempReal = leseWert('ns=3;s="Daten_Raspberry"."Pufferspeicher_Sensorwerte"."Puffer"[%s]."Kran"."Sekunde"[%s]."Sensor"[%s]."minimum_Temp"' % (PufferStr, sek1, sens1)) 
				mittelKrTemp, mittelKrTempReal = leseWert('ns=3;s="Daten_Raspberry"."Pufferspeicher_Sensorwerte"."Puffer"[%s]."Kran"."Sekunde"[%s]."Sensor"[%s]."mittel_Temp"' % (PufferStr, sek1, sens1)) 
				maximumKrTemp, maximumKrTempReal = leseWert('ns=3;s="Daten_Raspberry"."Pufferspeicher_Sensorwerte"."Puffer"[%s]."Kran"."Sekunde"[%s]."Sensor"[%s]."maximum_Temp"' % (PufferStr, sek1, sens1))

				minimumKrTempListe.append(round(minimumKrTemp, 3))
				mittelKrTempListe.append(round(mittelKrTemp, 3))
				maximumKrTempListe.append(round(maximumKrTemp, 3))
				
Benutzeravatar
sparrow
User
Beiträge: 4164
Registriert: Freitag 17. April 2009, 10:28

Zu allererste solltest du anfangen deinen Variablen vernünftige Namen zu geben. Das hilft deutlich dabei zu verstehen was sie tun und wofür sie da sind.
Und wenn sich die Daten so sehr ähneln, dann möchte man die eigentlich zusammenfassen statt zu kopieren. Wird ja sonst unwartbar.

Ungetestet:

Code: Alles auswählen

from collections import defaultdict
sensors_data = defaultdict(list)
if max_sensor_id > 0:
    for sensor_id in range(0, max_sensor_id):
        value_names = ["minimum", "mittel", "maximum", "minimum_Temp", "mittel_Temp", "maximum_Temp"]
        for value_name in value_names:
            value, _ = leseWert(f'ns=3;s="Daten_Raspberry"."Pufferspeicher_Sensorwerte"."Puffer"{PufferStr}."Kran"."Sekunde"{sek1}."Sensor"{sensor_id}."{value_name}"'
            sensors_data[value_name].append(value)
Knausbär
User
Beiträge: 9
Registriert: Mittwoch 15. September 2021, 12:08

Danke erst einmal für deine Antwort.

Ich wollte deinen Vorschlag auch einmal ausprobieren. Allerdings kommt eine Fehlermeldung (mal abgesehen von der vergessenen Klammer). Und zwar kommt folgender Fehler:
opcua.ua.uaerrors._auto.BadNodeIdUnknown: "The node id refers to a node that does not exist in the server address space."(BadNodeIdUnknown)

Aber selbst mit deinem Vorschlag (der zugegeben sauberer aussieht) erhöht das doch nicht die Performance oder?
rogerb
User
Beiträge: 878
Registriert: Dienstag 26. November 2019, 23:24

@Knausbär,

Grundsätzlich, kann ich mir kaum vorstellen, dass Python zu langsam hierfür wäre. Was aber jetzt so lange dauert ist schwer zu sagen.

kannst du mal zeigen welche OPC Library du verwendest?
Diese vielleicht:
https://github.com/FreeOpcUa/python-opcua

Du baust die Verbindug anscheinen über einen Raspberry Pi auf?
Wie sieht der gesamte Code aus?
Je mehr Informationen du gibst, umso leichter ist es dir zu helfen.
Benutzeravatar
sparrow
User
Beiträge: 4164
Registriert: Freitag 17. April 2009, 10:28

@Knausbär: Es nützt nichts über Performance nachzudenken, bevor den Code audgeräumt hast. Wie willst du denn so messen, wo das Problem liegt? Für 500 Werte, die du liest, 500 Zeilen pasten, die einen Zeitstempel ausgeben? So etwas in der Art wirst du machen müssen um herauszufinden, wo das Problem liegt. Aber das willst du mit vernünftigem Code machen.

Und der Code ohne den Fehler müsste dann so aussehen:

Code: Alles auswählen

from collections import defaultdict
sensors_data = defaultdict(list)
if max_sensor_id > 0:
    for sensor_id in range(0, max_sensor_id):
        value_names = ["minimum", "mittel", "maximum", "minimum_Temp", "mittel_Temp", "maximum_Temp"]
        for value_name in value_names:
            value, _ = leseWert(f'ns=3;s="Daten_Raspberry"."Pufferspeicher_Sensorwerte"."Puffer"[{PufferStr}]."Kran"."Sekunde"[{sek1}]."Sensor"[{sensor_id}]."{value_name}"')
            sensors_data[value_name].append(round(value, 3))
Und wenn du etwas in der Art hast, der das in eine gute Datenstruktur bringt, dann kannst du in der Schleife jedes Mal schauen, wie viel Zeit vergangen ist. So findest du erst einmal das Bottleneck. Und dann kannst du dir Gedanken machen, ob man das angehen kann.
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Es wird ja nicht der entscheidende Code gezeigt, darum kann man nur raten. Aber da es sich um ein Client/Server system handelt, muss man natürlich eine Verbindung zum Server aufbauen, um dann Anfragen zu stellen. Und zumindest aus den Code Fragmenten lässt sich fürchten, dass genau das für jede Eigenschaft passiert. Statt einmal für alle.
Knausbär
User
Beiträge: 9
Registriert: Mittwoch 15. September 2021, 12:08

Hallo sparrow,

danke der Code funktioniert.
Allerdings muss ich zugeben das ich mit diesem deafultdict nicht auskenne. Die Daten werden bei mir nach dem auslesen über die OPCUA Schnittstelle in eine Datenbank geschrieben. Mit meiner einfachen Liste weiß ich wie das geht aber wie funktioniert dies mit deiner Variante?

Die Datenbank ist folgendermaßen aufgebaut:

Code: Alles auswählen

Jahr = str(datetime.now().strftime("%Y"))

database_Sensoren = sqlite3.connect("SensorenKran" + Jahr + ".db")
cursor_Sensoren = database_Sensoren.cursor()
cursor_Sensoren.execute("""CREATE TABLE IF NOT EXISTS Sensor1 (
						   Zeitstempel TEXT,
						   Wert_Min REAL,
						   Wert_Mit REAL,
						   Wert_Max REAL,
						   Wert_Temp_Min REAL,
						   Wert_Temp_Mit REAL,
						   Wert_Temp_Max REAL
						   )""")
cursor_Sensoren.execute("""CREATE TABLE IF NOT EXISTS Sensor2 (						  
						   Zeitstempel TEXT,
						   Wert_Min REAL,
						   Wert_Mit REAL,
						   Wert_Max REAL,
						   Wert_Temp_Min REAL,
						   Wert_Temp_Mit REAL,
						   Wert_Temp_Max REAL
						   )""")
das ganze geht dann bis Sensor 8.
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

@Knausbär: Die Sensornummer hat im Tabellennamen nichts verloren. Solche Informationen werden als Spalte in einer Tabelle gespeichert.
Jede Tabelle sollte auch eine explizite eindeutige ID für jeden Eintrag haben.
Abkürzungen haben weder was in Variablennamen noch in Feldnamen von Tabellen etwas zu suchen.

Code: Alles auswählen

database_sensoren = sqlite3.connect(f"SensorenKran{datetime.now():%Y}.db")
cursor = database_sensoren.cursor()
cursor.execute("""CREATE TABLE IF NOT EXISTS Sensor (
    id INTEGER NOT NULL PRIMARY KEY,
    sensor_nummer NUMBER,
    zeitstempel TIMESTAMP,
    wert_minimum REAL,
    wert_mittel REAL,
    wert_maximum REAL,
    temperatur_minimum REAL,
    temperatur_mittel REAL,
    temperatur_maximum REAL
    )""")
Knausbär
User
Beiträge: 9
Registriert: Mittwoch 15. September 2021, 12:08

Ok mein Problem mit der Datenbank konnte ich alleine lösen.
Ich habe nun mein Programm aufgeräumt.
Knausbär
User
Beiträge: 9
Registriert: Mittwoch 15. September 2021, 12:08

Ok vielleicht kann mir jemand einen Tip geben wo die Zeit verloren geht. So sieht der Code bisher aus.

Code: Alles auswählen

# Kran- und Katzwerte auslesen	
for sek in range(0, 60):		
	if sek > 0:
		aktZeitSek = int(aktZeitSek) + 1
	if aktZeitSek >= 60:
		aktZeitSek = aktZeitSek - 60
		aktZeitMin = Minute
		aktZeitStd = Stunde
		aktZeitDay = Tag
		aktZeitMon = Monat
		zeitkmpl = datetime.now().strftime("%Y")		

	sek1 = str(sek)
	# Kransensoren über OPCUA abfragen
	sensors_data_kr = defaultdict(list)	
	if max_sensor_id > 0:
	    for sensor_id in range(0, max_sensor_id):
	        value_names = ["minimum", "mittel", "maximum", "minimum_Temp", "mittel_Temp", "maximum_Temp"]
	        for value_name in value_names:		        	
	            value, _ = leseWert(f'ns=3;s="Daten_Raspberry"."Pufferspeicher_Sensorwerte"."Puffer"[{PufferStr}]."Kran"."Sekunde"[{sek1}]."Sensor"[{sensor_id}]."{value_name}"')
	            sensors_data_kr[value_name].append(round(value, 3))

	# Katzsensoren über OPCUA abfragen
	sensors_data_ka = defaultdict(list)	
	if max_sensor_id > 0:
	    for sensor_id in range(0, max_sensor_id):
	        value_names = ["minimum", "mittel", "maximum", "minimum_Temp", "mittel_Temp", "maximum_Temp"]
	        for value_name in value_names:
	            value, _ = leseWert(f'ns=3;s="Daten_Raspberry"."Pufferspeicher_Sensorwerte"."Puffer"[{PufferStr}]."Katze"."Sekunde"[{sek1}]."Sensor"[{sensor_id}]."{value_name}"')
	            sensors_data_ka[value_name].append(round(value, 3))

	# Hubwerksensoren über OPCUA abfragen
	sensors_data_hu = defaultdict(list)		
	if max_sensor_id > 0:
	    for sensor_id in range(0, max_sensor_id):
	        value_names = ["minimum", "mittel", "maximum", "minimum_Temp", "mittel_Temp", "maximum_Temp"]		        
	        for value_name in value_names:
	            value, _ = leseWert(f'ns=3;s="Daten_Raspberry"."Pufferspeicher_Sensorwerte"."Puffer"[{PufferStr}]."Hubwerk"."Sekunde"[{sek1}]."Sensor"[{sensor_id}]."{value_name}"')
	            sensors_data_hu[value_name].append(round(value, 3))			           	

	aktZeitSek = str(aktZeitSek)
	aktZeitSek = aktZeitSek.zfill(2)
	aktZeitMon = str(aktZeitMon)
	aktZeitMon = aktZeitMon.zfill(2)
	aktZeitDay = str(aktZeitDay)
	aktZeitDay = aktZeitDay.zfill(2)
	aktZeitStd = str(aktZeitStd)
	aktZeitStd = aktZeitStd.zfill(2)
	aktZeitMin = str(aktZeitMin)
	aktZeitMin = aktZeitMin.zfill(2)	
	zeitkmpl += "_" + aktZeitMon + "_" + aktZeitDay + "_" + aktZeitStd + "_" + aktZeitMin + "_" + aktZeitSek
	# print("Zeitstempel: " + zeitkmpl + ", Min: " + str(minimumKr) + ", Mittel: " + str(mittelKr) + ", Max: " + str(maximumKr) + ", sek: " + str(sek) + ", Sens: " + str(sens))
		
	# Kransensoren
	if Sensoren_Kr > 0:
		for sensor_id in range(0, Sensoren_Kr):
			eintrag = []
			schrID = "Sensor" + str(sensor_id + 1)
			eintrag = [(zeitkmpl,sensors_data_kr["minimum"][sensor_id],sensors_data_kr["mittel"][sensor_id],sensors_data_kr["maximum"][sensor_id],\
			sensors_data_kr["minimum_Temp"][sensor_id],sensors_data_kr["mittel_Temp"][sensor_id],sensors_data_kr["maximum_Temp"][sensor_id],)]

			cursor_SensorenKr.executemany(f"INSERT INTO {schrID} VALUES (?,?,?,?,?,?,?)", eintrag)							
	# Katzsensoren
	if Sensoren_Ka > 0:
		for sensor_id in range(0, Sensoren_Ka):
			eintrag = []
			schrID = "Sensor" + str(sensor_id + 1)
				eintrag = [(zeitkmpl,sensors_data_ka["minimum"][sensor_id],sensors_data_ka["mittel"][sensor_id],sensors_data_ka["maximum"][sensor_id],\
				sensors_data_ka["minimum_Temp"][sensor_id],sensors_data_ka["mittel_Temp"][sensor_id],sensors_data_ka["maximum_Temp"][sensor_id],)]

				cursor_SensorenKa.executemany(f"INSERT INTO {schrID} VALUES (?,?,?,?,?,?,?)", eintrag)			

	# Hubwerksensoren
	if Sensoren_Hu > 0:
		for sensor_id in range(0, Sensoren_Hu):
			eintrag = []
			schrID = "Sensor" + str(sensor_id + 1)
			eintrag = [(zeitkmpl,sensors_data_hu["minimum"][sensor_id],sensors_data_hu["mittel"][sensor_id],sensors_data_hu["maximum"][sensor_id],\
			sensors_data_hu["minimum_Temp"][sensor_id],sensors_data_hu["mittel_Temp"][sensor_id],sensors_data_hu["maximum_Temp"][sensor_id],)]

			cursor_SensorenKa.executemany(f"INSERT INTO {schrID} VALUES (?,?,?,?,?,?,?)", eintrag)					

	zeitkmpl = datetime.now().strftime("%Y")		

database_Sensoren_Kr.commit()
database_Sensoren_Ka.commit()
database_Sensoren_Hu.commit()

database_Sensoren_Kr.close()
database_Sensoren_Ka.close()
database_Sensoren_Hu.close()
Ich weiß das die Namen nicht optimal gewählt sind. Daran muss ich arbeiten. Was könnte ich sonst verbessern?
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Wie. Sieht. leseWert. Aus.
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

Jetzt hast Du ja noch immer die Sensor-ID in den Tabellennamen hineinkodiert. Ändere das am besten sofort. Es macht wenig Sinn, mit dem schlechten Datenbankdesign weiter zu arbeiten. Noch besser wäre es, wenn Du die Sensor-Gruppe auch als Tabellenspalte speicherst und nicht in verschiedene Datenbanken!

Benutze keine Abkürzungen. Was ist der Unterschied zwischen sek und sekl? Warum Kr, Ka und Hu?
Variablennamen werden per Konvention immer komplett klein geschrieben.
Der Code für Kran, Kratz und Hub ist weitgehend identisch.
Statt str und zfill benutzt man Formatstrings.
Was Du da mit den ganzen AktZeit-Variablen machst, ist sehr undurchsichtig und bestenfalls falsch. Rechne nicht selbst mit Minute, Sekunde und Stunde, sondern benutze dafür `datetime`. Du hast einen Zeitstempel, erfinde kein eigenes Datumsformat, sondern nutze das, das die Datenbank unterstützt!
Deine Datenstruktur ist ungünstig geschnitten, Du hast ein Wörterbuch mit Listen, statt dessen solltest Du eine Liste haben, wo jeder Eintag einen kompletten Datensatz beschreibt.
Bei INSERT sollte man immer alle Felder explizit angeben, das ist sogar unumgänglich, weil der Primary-Key ja automatisch gezählt wird.
Du benutzt executemany um immer nur EINEN Eintrag einzutragen. Warum?

Code: Alles auswählen

from collections import namedtuple

SensorWerte = namedtuple("SensorWerte", ["sensor_id", "minimum", "mittel", "maximum", "minimum_Temp", "mittel_Temp", "maximum_Temp"])

def read_sensors(sensor_group, max_sensor_id, puffer, sekunde):
    data = []
    for sensor_id in range(max_sensor_id):
        values = [sensor_id]
        for value_name in SensorWerte._fields[1:]:
            value, _ = leseWert(f'ns=3;s="Daten_Raspberry"."Pufferspeicher_Sensorwerte"."Puffer"[{puffer}]."{sensor_group}"."Sekunde"[{sekunde}]."Sensor"[{sensor_id}]."{value_name}"')
            values.append(round(value, 3))
        data.append(SensorWerte(values))
    return data
    
def insert_into_database(cursor, sensor_group, sensors):
    for sensor in sensors:
        cursor_sensor_kran.execute("""INSERT INTO Sensoren
            (sensor_gruppe, sensor_id, minimum, mittel, maximum, minimum_Temp, mittel_Temp, maximum_Temp, zeit)
            VALUES (?,?,?,?,?,?,?,?)""", (sensor_group,) + tuple(sensor) + (aktuelle_zeit,))

# Kran- und Katzwerte auslesen	
for sekunde in range(60):
    aktuelle_zeit = datetime(jahr, monat, tag, stunde, minute, sekunde)

	# Kransensoren über OPCUA abfragen
	sensors_kran = read_sensors("Kran", max_sensor_id, PufferStr, sekunde)

	# Katzsensoren über OPCUA abfragen
	sensors_katz = read_sensors("Katz", max_sensor_id, PufferStr, sekunde)

	# Hubwerksensoren über OPCUA abfragen
	sensors_hubwerk = read_sensors("Hubwerk", max_sensor_id, PufferStr, sekunde)

    cursor = database.cursor()
    insert_into_database(cursor, "Kran", sensors_kran)
    insert_into_database(cursor, "Katz", sensors_katz)
    insert_into_database(cursor, "Hubwerk", sensors_hubwerk)
    cursor.close()
    database.commit()
Knausbär
User
Beiträge: 9
Registriert: Mittwoch 15. September 2021, 12:08

Hallo,

zum ersten die Funktion "leseWert" sieht wie folgt aus:

Code: Alles auswählen

def leseWert(name):	
	var = client.get_node(name)
	varWert = var.get_value()	
	return varWert, var
Zum SensorID dies ist mit in dem Tabellennamen weil ich am Ende immer "reine" Sensorwerte ausgeben muss. Und wenn sich jetzt einer die kompletten Sensorwerte für Sensor 1 von dem letzten Jahr anschauen will fande ich es besser für die Performance nur eine Tabelle dafür durchsuchen zu müssen. Wir reden hier immerhin pro Sensor pro Sekunde von 6 Werten, das macht auf ein Jahr 31.536.000 Werte pro Sensor.
Wenn ich dann noch innerhalb einer Tabelle 8 Sensoren speichere macht das mal 8 schon 252.288.000 Werte. Und deshalb aber ich pro Sensor eine Tabelle angelegt.

Zum Thema Kr, Ka, Hu. Es gibt 3 Achsen mit jeweils 8 Sensoren pro Sensor werden 2 Werte aufgezeichnet. Ein Abstandwert und eine Kontakttemperatur. In der Siemens Steuerung werden diese Werte alle 100 ms aufgezeichnet und ein Minimum, Mittellwert und ein Maximumwert pro Sekunde ermittelt und dann über OPCUA abgefragt.

Ja mit den Variablennamen muss ich noch ein wenig arbeiten ich bin noch kein Profi. Sorry. :D

Zur Zeit: Die Zeiten von den Sensorwerten werden in der Steuerung erfasst und müssen nicht mit der aktuellen Zeit übereinstimmen. Deswegen wird dies mit übergeben und umgerechnet. Ich bin damit auch noch nicht zufrieden und arbeite an einem besseren System. Allerdings sollte da erst einmal die Performance des ganzen Systems besser sein. Denn wenn alle Sensoren und alle Achsen aktiv sind schaffe ich es im Moment nicht innerhalb einer Minute die Werte der letzten Minute abzuholen. :shock:

Und was meinst du mit einer Liste, wo jeder Eintrag einen kompletten Datensatz beschreibt?
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

Und jetzt willst Du dir die Maximaltemperatur aller Sensoren anschauen: ups.
Hast Du Dir die Performance schonmal angeschaut? Wenn Du denkst, dass mehrere Tabellen das Problem lösen, dann hast Du ein anderes Problem, denn das ist nicht die Lösung.

Was ich mit EINER Liste meine ist, dass es ungünstig ist, alle Minimalwerte in einer anderen Liste zu speichern als alle Maximalwerte, weil Minimalwert und Maximalwert zu EINEM Sensor gehören und nicht außeinandergerissen werden sollten.
Knausbär
User
Beiträge: 9
Registriert: Mittwoch 15. September 2021, 12:08

Sirius3 hat geschrieben: Donnerstag 16. September 2021, 15:34 Und jetzt willst Du dir die Maximaltemperatur aller Sensoren anschauen: ups.
Hast Du Dir die Performance schonmal angeschaut? Wenn Du denkst, dass mehrere Tabellen das Problem lösen, dann hast Du ein anderes Problem, denn das ist nicht die Lösung.

Was ich mit EINER Liste meine ist, dass es ungünstig ist, alle Minimalwerte in einer anderen Liste zu speichern als alle Maximalwerte, weil Minimalwert und Maximalwert zu EINEM Sensor gehören und nicht außeinandergerissen werden sollten.
Guten Morgen Sirius,

vielen Dank für deine Antwort.
Ich werde die Sensoren in eine Tabelle packen wenn du meinst das mehrer Tabellen die Performance nicht verbessern. Bleibt natürlich die Frage was die Performance verbessert oder was ich falsch mache.

Ich habe am Wochenende mal ein paar Test gemacht. Also die Abfrage an den OPCUA Server ist nicht das Problem. Das sind nur knapp 1.3 Sekunden für alle Werte. Bleibt also nur noch das Problem die ganzen Daten in die Datenbank einzutragen...

Vielen Dank.
Benutzeravatar
sparrow
User
Beiträge: 4164
Registriert: Freitag 17. April 2009, 10:28

Ich glauebe, es wäre ganz hilfreich deinen ganzen Code zu sehen. Grundsätzlich gilt, dass jedes insert in eine Datenbank eine Transaktion öffnet, die am Ende mit einem "commit" fest in die Datenbank geschrieben werden muss. "commit" ist recht teuer. Wenn man recht viele Daten auf einmal einfügen möche, ist es also sinnvoll das zu bünden, bevor man commit aufruft. Dazu kommt, dass sqlite3 - wenn ich mich richtig erinnere - mit autocommit läuft, wenn man kein isolation_level angibt. Dann wird sowieso für jedes Statement ein commit ausgeführt, was ebenfalls alng dauert.

Wenn du deine Datenbank so angepasst hast, dass alles in einer tabelle steht, kannst du recht viele gleichlautende Daten mit "executemany" einfügen, da das Statement gleich bleibt und nur die Values sich ändern.

Das dürfte dann deutlich flotter werden.
Knausbär
User
Beiträge: 9
Registriert: Mittwoch 15. September 2021, 12:08

Hallo sparrow,

der ganze Code umfasst in etwa 1800 Zeilen.
Ich werde die Datenbank heute zusammenführen. Mit dem "executemany" füge ich schon alle Daten eines Sensors mit einem mal in die Datenbank ein. Nur das ich das für die 60 Sekunden mit einem mal schaffe, daran beiße ich mir die Zähne aus. Da wäre ich für einen Tipp dankbar.
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

@Knausbär: bei Deinem letzten Code benutzt Du noch `executemany` falsch, also wäre es gut, wenn Du Deinen aktuell benutzen Code hier posten würdest. Und wenn Du all das, was Dir hier als Tipps gegeben wurde, umgesetzt hast, sind es dann immer noch 1800 Zeilen Code?
Knausbär
User
Beiträge: 9
Registriert: Mittwoch 15. September 2021, 12:08

@Sirius3: ich bastel morgen die Datenbanken einmal um. Und poste dann den relevanten Code. Und wenn ich alle Tipps umsetze kommen wir vielleicht auf 1200 Zeilen Code.
Benutzeravatar
DeaD_EyE
User
Beiträge: 1012
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

rogerb hat geschrieben: Donnerstag 16. September 2021, 07:46 @Knausbär,

Grundsätzlich, kann ich mir kaum vorstellen, dass Python zu langsam hierfür wäre. Was aber jetzt so lange dauert ist schwer zu sagen.

Nein, es seiden Python schafft es nicht alle 100 ms irgendwas zu machen.
Die Samplerate beträgt bei den normalen Modellen 100 ms und die kostspieligen können sogar 10 ms.
Auch das ist kein Problem für Python, es seiden man macht die Aufrufe zu komplex, dass sie länger als 100 ms brauchen.

Generell würde ich die Pfade zusammenfassen, um Copy&Pase-Fehler zu verhindern.
Man kann auch Listen mit einzelnen str nutzen, um die Symbole zu addressieren.

Ein weiter Vorteil ist es, wenn man bei der SPS eine OPC-UA-Spezifikation anlegt und anstatt auf die Standard-Stimatic-Schnitstelle, auf seine eigene zugreift.
Ich glaube das geht aber erst seit Tia Portal v15. Aktuell ist V17. Mit den verdammten Installationen komme ich gar nicht mehr nach.
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
Antworten