Ausgabe umformen und in Datei speichern

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
frannek
User
Beiträge: 33
Registriert: Dienstag 28. Januar 2014, 12:17

Hallo Zusammen,

ich bin mehr als neu und schreibe gerade ein kleines Tool, welche Daten aus dem Modbus ausliest. Das funktioniert soweit ganz gut doch leider komme ich jetzt an meine Grenzen.

Es geht um folgendes Skript:

Code: Alles auswählen

#!/usr/bin/env python
#IMPORT VON DATUM UND UHRZEIT
import datetime
datum = []
uhrzeit = []
heute = datetime.date.today()
datum.append(heute)


# MODBUS-ADAPTER AN COM PORT KONFIGURIEREN
import minimalmodbus
minimalmodbus.BAUDRATE = 19200
minimalmodbus.PARITY = 'E'
minimalmodbus.BYTESIZE = 8
minimalmodbus.stopbits = 1
minimalmodbus.TIMEOUT = 0.02

#DEFINITION VON HARDWARE UND SLAVE-ADRESSE
instrument1 = minimalmodbus.Instrument('/dev/ttyS0', 31)
instrument2 = minimalmodbus.Instrument('/dev/ttyS0', 33)
instrument3 = minimalmodbus.Instrument('/dev/ttyS0', 20)
instrument4 = minimalmodbus.Instrument('/dev/ttyS0', 16)
instrument5 = minimalmodbus.Instrument('/dev/ttyS0', 32)



#AUSLESEN VON REGISTER 2 ( ACHTUNG: REGISTER 1 IST 0) UND DEFINITION VON preassure
preassure1 = instrument1.read_registers(1, 1, 4)
preassure2 = instrument2.read_registers(1, 1, 4)
preassure3 = instrument3.read_registers(1, 1, 4)
preassure4 = instrument4.read_registers(1, 1, 4)
preassure5 = instrument5.read_registers(1, 1, 4)



#AUSGABE VON PREASSURE
print "SENSOR1\t","1\t",preassure1,"\t",heute.strftime('%d.%m.%Y'),"\t",datetime.datetime.now().strftime("%I:%M:%S")
print "SENSOR2\t","2\t",preassure2,"\t",heute.strftime('%d.%m.%Y'),"\t",datetime.datetime.now().strftime("%I:%M:%S")
print "SENSOR3\t","3\t",preassure3,"\t",heute.strftime('%d.%m.%Y'),"\t",datetime.datetime.now().strftime("%I:%M:%S")
print "SENSOR4\t","4\t",preassure4,"\t",heute.strftime('%d.%m.%Y'),"\t",datetime.datetime.now().strftime("%I:%M:%S")
print "SENSOR5\t","5\t",preassure5,"\t",heute.strftime('%d.%m.%Y'),"\t",datetime.datetime.now().strftime("%I:%M:%S")





Dieses Skript liest aus dem Modbus bestimmter Adressen die Register aus.

die Ausgabe hierzu sieht so aus:

Code: Alles auswählen

SENSOR1	1	[4131] 	28.01.2014 	12:14:13
SENSOR2	2	[4092] 	28.01.2014 	12:14:13
SENSOR3	3	[4052] 	28.01.2014 	12:14:13
SENSOR4	4	[4044] 	28.01.2014 	12:14:13
SENSOR5	5	[4077] 	28.01.2014 	12:14:13


Erklärung:
Bezeichnung des Sensors / Datenbank ID/ Druck / Datum / Uhrzeit

Nun ist es so, dass ich zwischen den einzelnen Segmetnten durch ein \t einen Tabulator gesetzt habe. Das ist soweit auch in Ordnung. Leider tauchen hinter den Modbus-Werten und hinter dem Datum ein Leerzeichen auf. Das ist nicht so dolle. Das nächste ist die [] um dem ausgelesenen Wert. Diese Klammer möchte ich gerne weg haben.
Vor langer Zeit hatte ich mal was ähnliches in PHP gemacht. Dort musste ich, logischer weise, vor dem Print die Variabel nochmal auslesen, zeichen entfernen und als andere Variable setzen. Leider habe ich das hier absolut nicht hinbekommen.
Ich würde mich freuen, wenn mir hier jemand helfen könnte.

Das speichern in einer Datei... na ja... das gehe ich danach erstmal selbst an und würde mich freuen, im Zweifel nochmal fragen zu dürfen.

Vielen Dank vom absoluten Python-Neuling

Frannek
Benutzeravatar
darktrym
User
Beiträge: 784
Registriert: Freitag 24. April 2009, 09:26

Ich lass die Kritik bzgl. unnötiger Redundanz mal weg, mir scheints hier mangelts an Wissen welches so in jedem Tutorial vorkommt.
Wenn dir preassure? eine Liste zurückgibt welches ohnehin nur ein Wert beinhaltet, kannst auch über den Index darauf zugreifen.
Natürlich werden überall Leerzeichen auftauchen, da du Parameter print übergibst welches von Hause aus ein Seperator in Form von eben jenen Zeichen nutzt. Also entweder String formatieren oder sys.stdout.write verwenden oder print Befehl über __future__ Import.

Wenn du die Ausgabe noch speichern willst, ich nehme an du willst beides Ausgabe auf Bildschirm und in Datei würde sich die Formatierung anbieten und den Ausgabeteil in einem schönen With Block.
„gcc finds bugs in Linux, NetBSD finds bugs in gcc.“[Michael Dexter, Systems 2008]
Bitbucket, Github
mutetella
User
Beiträge: 1695
Registriert: Donnerstag 5. März 2009, 17:10
Kontaktdaten:

@frannek
Zeilen 4 - 7 machen keinen Sinn.
Zeilen 19 - 23 lassen sich auch so

Code: Alles auswählen

instruments = [minimalmodbus.Instrument('/dev/ttyS0', slave) for slave in (31, 33, 20, 16, 32)]
verkürzen. Damit vereinfacht sich dann auch die Ausgabe (ungetetest):

Code: Alles auswählen

for index, instrument in enumerate(instruments):
    index += 1
    pressure = instrument.read_registers(1, 1, 4)
    print 'SENSOR{index}\t{index}\t{pressure}\t{date:%d.%m.%Y}\t{date:%I:%M:%S}'.format(index=index, pressure=pressure, date=datetime.datetime.now())
mutetella


EDIT: Wobei ich das mit dem Datum nicht verstehe... sollten dort nicht die Zeiten stehen, zu denen die Werte auch ausgelesen wurden?
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit ;-) )
BlackJack

@mutetella: Das bekommt man noch eine Zeile kürzer wenn man `enumerate()` sagt es soll von 1 an zu zählen. :-)
frannek
User
Beiträge: 33
Registriert: Dienstag 28. Januar 2014, 12:17

Hallo und Danke für die Atworten.

Ich gehe erstmal auf die Fragen ein:


Das was ich jetzt hier als Print darstelle ist eher für mich und im Grunde nur zur Kontrolle ob das, was ich bislang gemacht habe auch wirklich funktioniert. Am ende soll das Print natürlich raus und dann wirklich nur in einem File gespeichert werden.

Die Zeilen 4-7 habe ich nur eingefügt, weil ich das im Manual so gesehen habe und auf Grund dessen, dass ich unten im Print ja auch das Datum und die Zeit in einem bestimmten Format haben möchte.

Die Ausgabe als Beispiel hat leider nicht funktioniert. Hier gabs dann gleich eine Fehlermeldung (und wenn ich es richtig gedeutet habe, dann jammert er bei der ersten Zeile des zweiten Codes.

Die Zeiten sind die Zeitpunkte, wan der Druck (also preassure) an dem Sensor ausgelesen wurde. Das hatte ja bislang funktioniert. Die Ausgabe muss im Grunde so aussehen:

BEZEICHNUNG<TAB>SENSOR-ID<TAB>SENSORWERT<TAB>DATUM<TAB>UHRZEIT

Sensorwert = X,XXX (und nicht [XXXX])

Wie gesagt... ich mach gerade alles durch learning by doing. Dass man es noch schöner programmieren kann, ist mir auch klar:-) Aber ich bin ja auch lernfähig und habe die Scriptvorschläge soweit auch verstanden. Ich bin jetzt auch nicht jemand, der sich hier etwas programmieren lassen möchte (gibt es sicher zu Hauf). Einen Tipp, wo ich was bestimmtes nachlesen kann ist ja erstmal ausreichend (hab ich bislang ja auch so gemacht). Nur leider weis ich nie, wonach ich suchen soll :-)

Besten Dank

Frannek
BlackJack

@frannek: Die Zeilen 4-7 hast Du also geschrieben ohne zu verstehen was sie tun. Das ist beim Programmieren kein sinnvolles vorgehen.

Wenn es Fehlermeldungen gibt, dann wäre es sinnvoll zu verraten welche das sind. Sonst kann man da schlecht weiterhelfen.

Die Zeiten sind eben nicht die Zeitpunkte wann gemessen wurde, sondern wann die Ausgabe gemacht wird. `now()` heisst auf deutsch ”jetzt” und liefert Zeit und Datum des Aufrufs dieser Funktion. Man sollte ermitteln von Zeit und Datum nicht trennen und werd Dir klar wann das passieren soll. Einmal vor denn Messungen, tatsächlich *zu* den einzelnen Messungen, oder bei der Ausgabe. Wobei letzteres vielleicht nicht wirklich viel Sinn macht.

Entsprechende Datenstrukturen statt durchnummerierter Namen zu verwenden ist IMHO schon keine Schönheitsfrage mehr. Das wirkt sich direkt darauf aus wie wartbar ein Programm ist wenn es aus lauter kopieren und einfügen und geringfügig ändern besteht.
frannek
User
Beiträge: 33
Registriert: Dienstag 28. Januar 2014, 12:17

@Black

Fehler ist dieser:

Code: Alles auswählen

 File "./modbus1.py", line 24
    for index, instrument in enumerate(instruments):
    ^
IndentationError: unexpected indent
Wenn ich es nicht als skript sondern einzeln abfeuer dann verlangt er bei

Code: Alles auswählen

for index, instrument in enumerate(instruments):
eine Eingabe

Die Zeit hinten raus ist nicht so dramatisch wichtig.. die Abfrage dauert eine Sekunde und soll ja in der Regel nur alle 15 Min bzw einmal am Tage gemacht werden. Da ist es egal ob eine min vorher oder danach auch der Wert tatsächlich ermittelt wurde. Aus diesem Grund hab ich es mir eben Einfach gemacht. Ich wollte im Grunde ja auch nur sehen, ob das ,was ich vorhabe auch umsetzbar ist und funktioniert. Macht es ja. Doch wie gesagt... ich lerne dazu und bin nicht auf 1000te Stunde nder Programmierung gekommen, wie so manc handerer. Bei mir sind es mit Python gerade mal 10 Stunden in denen ich mich mit Python befasse. Deswegen bitte ich hier noch um Nachsicht
Benutzeravatar
darktrym
User
Beiträge: 784
Registriert: Freitag 24. April 2009, 09:26

IndentationError behebt man indem man die ersten drei Zeilen vom Wikipedia Artikel mal liest.
„gcc finds bugs in Linux, NetBSD finds bugs in gcc.“[Michael Dexter, Systems 2008]
Bitbucket, Github
Antworten