Seite 1 von 1
"Beschriftung" einmalig in csv Kopfzeile schreiben
Verfasst: Mittwoch 13. Juni 2018, 17:39
von ICookie
Hallo,
ich habe folgendes Problem:
Mein Programm soll alle 5 Sekunden einen Feinstaubwert in eine .csv Datei schreiben. 1 Tag entspricht hierbei einer .csv Datei.
Jetzt soll es aber immer, wenn es für einen neuen Tag eine .csv Datei erstellt, in die ersten beiden Zeilen die "Beschriftung" einfügen.
Jedoch weiß ich nicht wie ich das anstellen soll. Werte abspeichern und neue Datei erstellen funktioniert ohne Probleme nur dort bin ich eben ratlos.
Code: Alles auswählen
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import serial, time, struct, csv
from datetime import datetime as DateTime
ser = serial.Serial('/dev/feinstaub', 9600)
byte = "\x00"
OUTPUT_FILENAME = "/home/pi/Documents/Feinstaubdatentest/Feinstaubdaten{:%Y%m%d}.csv"
Name = ["Feinstaubsensor"]
Beschriftung = ["Datum","Uhrzeit","PM2.5","PM10"]
now = DateTime.now().strftime("%Y-%m-%d;%H:%M:%S")
Datum, Uhrzeit = now.split(";")
with open(OUTPUT_FILENAME.format(DateTime.now()), 'a') as csvfile:
output = csv.writer(csvfile, delimiter=';', escapechar=' ', quoting=csv.QUOTE_NONE)
output.writerow(Name)
output.writerow(Beschriftung)
while True:
lastbyte = byte
byte = ser.read(size=1)
if lastbyte == "\xAA" and byte == "\xC0":
sentence = ser.read(size=9)
readings = struct.unpack('<HHxxBBB',sentence)
pm_25 = readings[0]/10.0
pm_10 = readings[1]/10.0
with open(OUTPUT_FILENAME.format(DateTime.now()), 'a') as csvfile:
output = csv.writer(csvfile, delimiter=';', escapechar=' ', quoting=csv.QUOTE_NONE)
output.writerow([Datum, Uhrzeit, pm_25, pm_10])
time.sleep(5)
Ich wäre um eine kleine Hilfe dankbar.
Re: "Beschriftung" einmalig in csv Kopfzeile schreiben
Verfasst: Mittwoch 13. Juni 2018, 18:13
von __blackjack__
Du musst Dir halt den Dateinamen merken und jedes mal wenn der sich ändert, als erstes die beiden Kopfzeilen schreiben. So etwas ähnliches machst Du in der Schleife ja schon mit `byte`/`lastbyte`.
`lastbyte` ist übrigens falsch oder zumindest irreführend. Das hiesse besser `previous_byte`.
Und Du schreibst für alle Datensätze das gleiche Datum und die gleiche Uhrzeit in jeden Datensatz. Das macht wenig Sinn.
Re: "Beschriftung" einmalig in csv Kopfzeile schreiben
Verfasst: Mittwoch 13. Juni 2018, 18:58
von ICookie
Hey,
würde das dann so funktionieren oder habe ich da einen Denkfehler?
Code: Alles auswählen
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import serial, time, struct, csv
from datetime import datetime as DateTime
import os.path
ser = serial.Serial('/dev/feinstaub', 9600)
byte = "\x00"
OUTPUT_FILENAME = "/home/pi/Documents/Feinstaubdatentest/Feinstaubdaten{:%Y%m%d}.csv"
Name = ["Feinstaubsensor"]
Beschriftung = ["Datum","Uhrzeit","PM2.5","PM10"]
now = DateTime.now().strftime("%Y-%m-%d;%H:%M:%S")
Datum, Uhrzeit = now.split(";")
#with open(OUTPUT_FILENAME.format(DateTime.now()), 'a') as csvfile:
# output = csv.writer(csvfile, delimiter=';', escapechar=' ', quoting=csv.QUOTE_NONE)
# output.writerow(Name)
# output.writerow(Beschriftung)
while True:
previous_byte = byte
byte = ser.read(size=1)
if previous_byte == "\xAA" and byte == "\xC0":
sentence = ser.read(size=9)
readings = struct.unpack('<HHxxBBB',sentence)
pm_25 = readings[0]/10.0
pm_10 = readings[1]/10.0
if os.path.exists(OUTPUT_FILENAME.format(DateTime.now())):
with open(OUTPUT_FILENAME.format(DateTime.now()), 'a') as csvfile:
output = csv.writer(csvfile, delimiter=';', escapechar=' ', quoting=csv.QUOTE_NONE)
output.writerow([Datum, Uhrzeit, pm_25, pm_10])
else:
with open(OUTPUT_FILENAME.format(DateTime.now()), 'w') as csvfile:
output = csv.writer(csvfile, delimiter=';', escapechar=' ', quoting=csv.QUOTE_NONE)
output.writerow(Name)
output.writerow(Beschriftung)
time.sleep(5)
Und warum schreibe ich immer das selbe Datum in die Datei? Auszug aus einer Datei:
Code: Alles auswählen
2018-05-06;00:00:38;1.5;1.6
2018-05-06;00:00:43;1.5;1.6
2018-05-06;00:00:48;1.5;1.6
2018-05-06;00:00:53;1.5;1.6
2018-05-06;00:00:58;1.6;1.7
2018-05-06;00:01:03;1.6;1.7
2018-05-06;00:01:08;1.6;1.7
2018-05-06;00:01:13;1.3;1.4
2018-05-06;00:01:18;1.3;1.4
2018-05-06;00:01:23;1.2;1.3
2018-05-06;00:01:28;1.2;1.3
2018-05-06;00:01:33;1.3;1.4
Re: "Beschriftung" einmalig in csv Kopfzeile schreiben
Verfasst: Mittwoch 13. Juni 2018, 19:21
von __blackjack__
Du machst da den Denkfehler das man den Dateinamen nicht mehrfach jedes mal mit dem neu abgefragtem Datum erstellen sollte, denn das kann sich ja von `DateTime.now()`-Aufruf zu `DateTime.now()`-Aufruf ändern. `DateTime.now()` sollte für jeden Schleifendurchlauf nur *einmal* aufgerufen werden. Dann drei Stellen im Code zu haben in der das dann in die gleiche Zeichenkette formiert wird, ist zwar kein Problem, aber machen muss man das auch nicht.
Und Du verlierst bei einem Dateiwechsel die gerade abgefragten Messdaten, weil Du dann nur die Kopfzeilen schreibst, aber nicht die Messdaten. Die müssen auf jeden Fall geschrieben werden. Da der Modus 'a' auch bei nicht-existierenden Dateien funktioniert, kannst Du da auch einiges an doppeltem Code beim öffnen/schreiben der Datei einsparen.
Warum Du immer das selbe Datum *und* die selbe Uhrzeit alle 5 Sekunden in die Datei schreibst, weiss ich nicht. Warum das Programm das tut dagegen schon: Weil Du das da so programmiert hast.
`Datum` und `Uhrzeit` ändern nicht auf magische Weise ihre Werte. Das muss man schon programmieren das sie für jeden Messvorgang die aktuellen Werte bekommen.
Edit: Der Ausschnitt aus der Datei kann nicht vom Programm im ersten Beitrag in diesem Thema kommen!
Re: "Beschriftung" einmalig in csv Kopfzeile schreiben
Verfasst: Mittwoch 13. Juni 2018, 20:05
von ICookie
Okay, danke. Ich werde das morgen mal versuchen.
Und doch, der Ausschnitt ist einer von einer Monatsmessung mit genau dem Code aus Beitrag 1. Warum sollte das nicht gehen?
//EDIT:
Oh, du hattest recht! Das ist der Code:
Code: Alles auswählen
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import serial, time, struct, csv
from datetime import datetime as DateTime
ser = serial.Serial('/dev/feinstaub', 9600)
byte = "\x00"
OUTPUT_FILENAME = "/home/pi/Documents/Feinstaubdatentest/Feinstaubdaten{:%Y%m%d}.csv"
Name = ["Feinstaubsensor"]
Beschriftung = ["Datum","Uhrzeit","PM2.5","PM10"]
with open(OUTPUT_FILENAME.format(DateTime.now()), 'a') as csvfile:
output = csv.writer(csvfile, delimiter=';', escapechar=' ', quoting=csv.QUOTE_NONE)
output.writerow(Name)
output.writerow(Beschriftung)
csvfile.close()
while True:
lastbyte = byte
byte = ser.read(size=1)
if lastbyte == "\xAA" and byte == "\xC0":
sentence = ser.read(size=9)
readings = struct.unpack('<HHxxBBB',sentence)
pm_25 = readings[0]/10.0
pm_10 = readings[1]/10.0
now = DateTime.now().strftime("%Y-%m-%d;%H:%M:%S")
Datum, Uhrzeit = now.split(";")
with open(OUTPUT_FILENAME.format(DateTime.now()), 'a') as csvfile:
output = csv.writer(csvfile, delimiter=';', escapechar=' ', quoting=csv.QUOTE_NONE)
output.writerow([Datum, Uhrzeit, pm_25, pm_10])
csvfile.close()
time.sleep(5)
Re: "Beschriftung" einmalig in csv Kopfzeile schreiben
Verfasst: Freitag 15. Juni 2018, 11:38
von __blackjack__
So hätte ich das umgesetzt (ungetestet):
Code: Alles auswählen
#!/usr/bin/env python
# coding: utf-8
from __future__ import absolute_import, division, print_function
import csv
import os
import time
from datetime import datetime as DateTime
from struct import Struct
from serial import Serial
SERIAL_PORT = '/dev/feinstaub'
OUTPUT_FILENAME_TEMPLATE = (
'/home/pi/Documents/Feinstaubdatentest/Feinstaubdaten{:%Y%m%d}.csv'
)
NAME = 'Feinstaubsensor'
HEADER_ROWS = [[NAME], ['Datum', 'Uhrzeit', 'PM2.5', 'PM10']]
READING_DELAY = 5 # In seconds.
SENTENCE_STRUCT = Struct('<HHxxBBB')
SENTENCE_START_MARKER = ('\xAA', '\xC0')
def main():
connection = Serial(SERIAL_PORT)
previous_byte = None
while True:
current_byte = connection.read()
if (previous_byte, current_byte) == SENTENCE_START_MARKER:
previous_byte = None
readings = SENTENCE_STRUCT.unpack(
connection.read(SENTENCE_STRUCT.size)
)
pm_25 = readings[0] / 10.0
pm_10 = readings[1] / 10.0
now = DateTime.now()
filename = OUTPUT_FILENAME_TEMPLATE.format(now)
is_new_file = not os.path.exists(filename)
with open(filename, 'a') as csv_file:
writer = csv.writer(
csv_file,
delimiter=';',
escapechar=' ',
quoting=csv.QUOTE_NONE,
)
if is_new_file:
writer.writerows(HEADER_ROWS)
writer.writerow(
[
format(now, '%Y-%m-%d'),
format(now, '%H:%M:%S'),
pm_25,
pm_10,
]
)
time.sleep(READING_DELAY)
else:
previous_byte = current_byte
if __name__ == '__main__':
main()