"Beschriftung" einmalig in csv Kopfzeile schreiben

Python auf Einplatinencomputer wie Raspberry Pi, Banana Pi / Python für Micro-Controller
Antworten
ICookie
User
Beiträge: 9
Registriert: Freitag 23. März 2018, 10:39

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.
Benutzeravatar
__blackjack__
User
Beiträge: 13007
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

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.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
ICookie
User
Beiträge: 9
Registriert: Freitag 23. März 2018, 10:39

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
Benutzeravatar
__blackjack__
User
Beiträge: 13007
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

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!
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
ICookie
User
Beiträge: 9
Registriert: Freitag 23. März 2018, 10:39

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)
Benutzeravatar
__blackjack__
User
Beiträge: 13007
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

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()
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Antworten