List index out of range

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
Zwerg
User
Beiträge: 3
Registriert: Montag 14. August 2017, 17:40

Hallo,

ich würde mich gerne erst einmal vorstellen. Habe nur sehr oberflächlich Erfahrung mit Python (ich arbeite mit Python 3.5.3) und arbeite mich gerade ein.

Arduino/C mache ich schon ein bisschen länger und arbeite gerade an einer autarken Energieversorgung. Dabei wird von Lithium Akkus per CAN Bus ein Arduino Nano genutzt, der die Daten per USB und virtuellem seriellen Port auf einen RasPi überträgt. Die Daten sehen so aus:

CAN Adresse,Messerttyp,Wert

also als Beispiel:

40,SOC,75

Nun möchte ich diese seriellen Daten gerne in eine Liste bzw. Array aufteilen. und mache das so ("import serial", Baudrate usw. funktioniert, das lasse ich mal raus):

Code: Alles auswählen

serCANbuf = str(serCAN.readline().decode().strip('\r\n'))
serCANbuf = serCANbuf.split(',')
print(serCANbuf) # Resultat: ['40', 'SOC', '75'], soweit so gut
print(serCANbuf[0]) # Resultat: 40, auch gut
print(serCANbuf[-1]) # Resultat: 75, auch gut, letztes Element der Liste
print(serCANbuf[1]) # Resultat: IndexError: list index out of range
Eigentlich hatte ich erwartet. Da index 0 und -1 funktionieren, stehe ich hier echt auf dem Schlauch. Habe ich da vielleicht etwas übersehen? Wäre für Anregungen sehr dankbar :-)
Zuletzt geändert von Anonymous am Montag 14. August 2017, 19:18, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
__deets__
User
Beiträge: 14493
Registriert: Mittwoch 14. Oktober 2015, 14:29

Glaube ich nicht. Das hier geht:

Code: Alles auswählen

Python 3.5.2 (v3.5.2:4def2a2901a5, Jun 26 2016, 10:47:25)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> serCANbuf = ['40', 'SOC', '75']
>>> print(serCANbuf) # Resultat: ['40', 'SOC', '75'], soweit so gut
['40', 'SOC', '75']
>>> print(serCANbuf[0]) # Resultat: 40, auch gut
40
>>> print(serCANbuf[-1]) # Resultat: 75, auch gut, letztes Element der Liste
75
>>> print(serCANbuf[1]) # Resultat: IndexError: list index out of range
SOC
Insofern muss da bei dir noch ein anderer Wurm drin sein. Auch wenn du glaubst der Rest tut nichts zur Sache, zeige ihn bitte mal.
Zwerg
User
Beiträge: 3
Registriert: Montag 14. August 2017, 17:40

Sehr gerne, bin noch am Anfang also verwende ich die deklarierten globalen variablen noch nicht.

Code: Alles auswählen

import serial

serCANport = '/dev/ttyUSB0' # CAN serial port
serCANbaud = 115200 # CAN serial baud rate

serCAN = serial.Serial(serCANport, serCANbaud)

# Define global variables
NumPacks = 5 # Total number of battery packs
essNo = [0, 1, 2, 3, 4] # Number of each pack for data arrays
essID = [10, 20, 30, 40, 50] # Equivalent CAN ID/address of each pack
essSOC = []
essSOH = []
essCurrent = []
essVoltage = []
essHiTemp = []
essLoTemp = []
essWarnFlag = []

# Main loop ----------------------------
while True:
	if (serCAN.inWaiting()>0):
		serCANbuf = str(serCAN.readline().decode().strip('\r\n'))
		serCANbuf = serCANbuf.split(',')
		print(serCANbuf)
		print(serCANbuf[0])
		print(serCANbuf[-1])
		print(serCANbuf[1])
Wenn ich zwischendrin den String serCANbuf = ['40', 'SOC', '75'] fest definiere geht es bei mir auch, dann bekomme ich als Output:

Code: Alles auswählen

['40', 'SOC', '75']
40
75
SOC
Wenn ich das nicht fest definiere aber print(serCANbuf[1]) auskommentiere, dann geht es auch, hier ein Beispiel vom Output:

Code: Alles auswählen

['50', 'SOC', '751']
50
751
Hier dann wieder einkommentiert:

Code: Alles auswählen

python3 krftwrk_sysctl.py 
['']


Traceback (most recent call last):
  File "krftwrk_sysctl.py", line 28, in <module>
    print(serCANbuf[1])
IndexError: list index out of range
Und soeben habe ich den Fehler wohl selbst gefunden. Ich kriege als erste Zeile vom seriellen eingang eine Leerzeile [''], das kann nicht gehen, wie dumm von mir. Danke für deine Hilfe, da hatte ich nicht gründlich geschaut...
Zuletzt geändert von Anonymous am Montag 14. August 2017, 19:20, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
Zwerg
User
Beiträge: 3
Registriert: Montag 14. August 2017, 17:40

Habe den relevanten Teil jetzt umgebaut, damit nur weiter gearbetet wird, wenn sich in der Liste auch ordnungsgemäß 3 Elemente befinden und jetzt klappt es:

Code: Alles auswählen

# Main loop ----------------------------
while True:
	if (serCAN.inWaiting() > 0):
		serCANbuf = str(serCAN.readline().decode().strip('\r\n'))
		serCANbuf = serCANbuf.split(',')
		if (len(serCANbuf) == 3):
			print(serCANbuf)
			print(serCANbuf[0])
			print(serCANbuf[-1])
			print(serCANbuf[1])
Danke für den Hinweis, dass das Problem woanders herkommen musste.
Zuletzt geändert von Anonymous am Montag 14. August 2017, 19:30, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
BlackJack

@Zwerg: Gut das Du die globalen Variablen noch nicht verwendest — fang damit besser auch gar nicht erst an. Auf Modulebene sollte man nur Code stehen haben der Konstanten, Funktionen, und Klassen definiert. Das Hauptprogramm steht üblicherweise in einer Funktion die `main()` heisst.

Die Namenschreibweise weicht vom Style Guide for Python Code ab.

Kann es sein das `NumPacks` redundant ist? Das ergibt sich doch aus der Länge der Listen mit Nummern und IDs. Zudem kann man hier den Verdacht haben das diese ganzen Listen später Werte haben die pro Index zusammengehören, also eigentlich gar nicht auf mehrere Listen aufgeteilt werden sollten.

Viele der Kommentare sind überflüsig, beziehungsweise wären es mit nur kleinen Änderungen von Namen.

Im die ``if``-Bedingung gehören keine Klammern. Und was soll dieses ``if`` überhaupt bewirken? Das macht zumindest in dem gezeigten Code keinen Sinn.

Der `str()`-Aufruf ist ebenfalls sinnlos.
Antworten