Seite 1 von 1
Dynamische Variablendeklaration
Verfasst: Samstag 1. Oktober 2016, 21:36
von pythonitas
Hallo alle zusammen,
ich habe mir mit Python3.4 und dem RaspPi3 eine Ofensteuerung gebaut.
Funktioniert auch alles, jedoch ist der Code teilweise unelegant und deswegen sehr lang, und das würde ich gern optimieren.
Funktionsbeschreibung
###################
In einer Textdatei habe ich ein Temperaturprofil hinterlegt nach folgendem Schema(sek=Sekunden, Temp=Soll-Temperatur):
Sek Temp
=========
010 035
020 054
030 072
040 109
usw.
Die Werte sind jeweils 3stellig und bei Bedarf um eine Null ergänzt, getrennt durch ein Leerzeichen.
Damit kann ich dann verschiedene Profile durch verschiedene Dateien einlesen.
Die Datei lese ich ein und speichere die Werte als Variable. Damit fahre ich dann eine Temperaturrampe ab.
Aktuelles Code-Schema
##################
Code: Alles auswählen
f=open("Datei")
zeilen=f.readlines()
# 1. Zeile auslesen
zeile1=zeilen[0]
zeit1=int(zeile1[0:3])
temp1=int(zeile1[4:7])
# 2. Zeile auslesen
zeile2=zeilen[1]
zeit2=int(zeile2[0:3])
temp2=int(zeile2[4:7])
# usw.
Zielcode
#######
Ich würde es gern nach folgendem Schema umsetzen, schaffe es aber nicht.
Code: Alles auswählen
f=open("Datei")
zeilen=f.readlines()
i=1
# Zeilen auslesen
while i<10:
zeile(i)=zeilen[i-1]
zeit(i)=int(zeile(i)[0:3])
temp(i)=int(zeile(i)[4:7])
i+=1
# usw.
Wie muss ich vorgehen, dass "zeile(i)" usw. richtig umgesetzt wird und dann per Inkrementierung der Reihe nach eingelesen wird?
Danke schonmal und einen schönen Abend.
Re: Dynamische Variablendeklaration
Verfasst: Samstag 1. Oktober 2016, 22:33
von nezzcarth
Statt durchnummerierter Variablen nimmt man dafür eher eine geeignete Datenstruktur, etwa ein Dictionary oder eine Liste.
Hier mal ein Vorschlag, wie man das vielleicht manchen könnte
Code: Alles auswählen
#!/usr/bin/env python3
import argparse
import re
PATTERN = re.compile(r'(?P<second>\d{3})\s(?P<temperature>\d{3})')
def main():
parser = argparse.ArgumentParser()
parser.add_argument('file_name')
args = parser.parse_args()
times = dict()
with open(args.file_name) as fh:
for line in fh:
result = re.match(PATTERN, line)
if result:
times[result.group('second')] = result.group('temperature')
print(times)
if __name__ == '__main__':
main()
(Doppelte Uhrzeiten werden zur Zeit überschrieben; je nach Ziel könnte sich z. B. ein defaultdict eignen)
Re: Dynamische Variablendeklaration
Verfasst: Sonntag 2. Oktober 2016, 08:41
von Sirius3
@pythonitas: was Du suchst, ist eine Liste:
Code: Alles auswählen
zeiten = []
temperaturen = []
with open("Datei") as lines:
for line in lines:
zeit, temperatur = map(int, line.split())
zeiten.append(zeit)
temperaturen.append(temperatur)
print(zeiten[0], temperaturen[0])
Eine feste Anzahl an Stellen für Werte in einer Datei zu haben, ist unüblich. Wenn man ein Trennzeichen (hier Leerzeichen) hat, dann kann man die Zeilen ja einfach an diesem Zeichen aufspalten.
Statt zwei getrennter Listen will man die Werte pro Zeile enger beieinander haben, entweder mit Hilfe von namedtuplen:
Code: Alles auswählen
from collections import namedtuple
ZeitMitTemperatur = namedtuple("ZeitMitTemperatur", "zeit,temperatur")
temperaturen = []
with open("Datei") as lines:
for line in lines:
temperaturen.append(ZeitMitTemperatur(*map(int, line.split())))
print(temperaturen[0].zeit, temperaturen[0].temperatur)
oder gleich in einem numpy-Array:
Code: Alles auswählen
import numpy
temperaturen = numpy.genfromtxt("Datei", names=["zeit","temperatur"])
print(temperaturen[0]['zeit'], temperaturen[0]['temperatur'])
Re: Dynamische Variablendeklaration
Verfasst: Sonntag 2. Oktober 2016, 08:45
von bwbg
Die RE-Keule für eine Angelegenheit, welche sich mit Zeichenkettenoperationen erledigen lassen?
Ungetestet:
Code: Alles auswählen
result = {int(s): int(t) for s, t in (line for line in islice(file, 1, None))}
Re: Dynamische Variablendeklaration
Verfasst: Sonntag 2. Oktober 2016, 09:24
von nezzcarth
bwbg hat geschrieben:
Die RE-Keule für eine Angelegenheit, welche sich mit Zeichenkettenoperationen erledigen lassen?
Die konkrete Aufgabe lässt sich mit Zeichenkettenoperationen schnell lösen. Wenn das Muster allerdings doch komplexer wird, als zunächst angenommen, werden diese schnell unhandlich. Da das bei solchen Parsingaufgaben durchaus vorkommen kann, finde ich es angemessen, gleich reguläre Ausdrücke zu verwenden; der overhead, der bei dem kleinen Skript entsteht ist ja nicht so riesig.
Re: Dynamische Variablendeklaration
Verfasst: Sonntag 2. Oktober 2016, 11:28
von Sirius3
@nezzcarth: ich sehe da eine Folge von durch Leerzeichen getrennte Zahlen und kein Muster der Form 3 Ziffern 1 Leerzeichen, 3 Ziffern und danach irgendetwas beliebiges. Eine natürliche Erweiterung solcher Daten ist dann nicht exakt 3 Ziffern, Kommazahlen, mehr als 2 Zahlen pro Zeile, etc. Da werden reguläre Ausdrücke beliebig komplex und schwer zu lesen.
Re: Dynamische Variablendeklaration
Verfasst: Sonntag 2. Oktober 2016, 11:47
von BlackJack
@nezzcarth: Es verletzt auch das KISS-Prinzip und grenzt an YAGNI. Wenn die Daten dann tatsächlich anders aussehen, ist es leicht `re` statt `split()` zu verwenden. Wenn sie nicht anders aussehen hat man unnötig `re` verwendet. Es geht ja nicht nur um die Komplexität des Ausdrucks den Du da verwendest, sondern das jemand der es liest und dann schaut was `re` eigentlich ist/macht eher erschlagen wird von Informationen und komischer zusätzlicher Syntax, als wenn man einfach nur `str.split()` nachliest.
Edit: Mit einem ähnlichen Argument könnt man dann auch gleich `pyparsing` verwenden, weil das wie Sirius3 anmerkt auch mit regulären Ausdrücken schnell unübersichtlich werden kann, und man dann vielleicht lieber eine lesbarere Grammatik verwenden möchte.

Re: Dynamische Variablendeklaration
Verfasst: Sonntag 2. Oktober 2016, 12:26
von nezzcarth
Na gut, überzeugt -- vielleicht
(Was mir vorschwebt, ist beispielsweise, dass man noch die Spaltennamen in Zeile 1 sowie Kommentare verarbeiten und Syntaxfehler abfangen wollen würde. Das ließe sich beispielsweise einheitlich über drei reguläre Ausdrücke lösen, die nacheinander geprüft werden. Im Prinzip landet man dann bei einer einheitlichen Programmstruktur, die relativ unabhängig von der konkreten Anzahl der Regeln ist. Oder würde man das eher nicht so machen? Aber ich sehe ein, dass, hier BlackJacks YAGNI-Einwand vielleicht auch greift.)
Re: Dynamische Variablendeklaration
Verfasst: Sonntag 2. Oktober 2016, 14:09
von snafu
Möglichst anfängerfreundlich ohne LC und ohne `map()`:
Code: Alles auswählen
def parse_data(filename):
result = list()
with open(filename) as infile:
for line in infile:
parts = line.split()
sekunden = int(parts[0])
temperatur = int(parts[1])
result.append((sekunden, temperatur))
return result
def print_data(data):
for sekunden, temperatur in data:
print(sekunden, temperatur)