CSV failide töötlemine Pythonis22. Oct '14

CSV failist ajatemplite ja näitude lugemine ning nende järgi tekstifaili, HTML ja Excel 2007 faili genereerimine:

# -*- coding: utf-8 -*-

FAILINIMI = "SCADAsync_5min.csv"

import numpy
from codecs import open # Impordib Python3 stiilis open()
from datetime import datetime
from pytz import timezone # Python 2.x

print "Loen:", FAILINIMI
m = []
now = datetime.now()
kpv_esimene = None
with open(FAILINIMI, encoding="utf-8") as fh:
    # Söö päis ära
    fh.readline()

    for line in fh:
        # Lõõ sõne laiali ; järgi
        tulbad = line.strip().split(";")

        # Parsi naiivne kellaaeg (ei tea ajatsooni)
        kpv_cet = datetime.strptime(tulbad[0], "%Y-%m-%d %H:%M:%S+00:00")

        # Pane ajatsooni info CET külge ja siis teisenda UTC-ks
        kpv_utc = kpv_cet.\
            replace(tzinfo=timezone("CET")).\
            astimezone(timezone("UTC"))

        if not kpv_esimene:
            kpv_esimene = kpv_utc

        # Tagantpoolt neljandast kuni lõpuni
        n2idud = tulbad[-4:]
        try:
            n1, n2, n3, n4 = [float(i) for i in n2idud]
        except ValueError:
            continue
        m.append(n1)

# Tee list numpy massiiviks
m = numpy.array(m)

# Arvuta keskmine numpy abil
average =  numpy.mean(m)

raporti_read = (
    u"Esimese näidu aeg: %s" % kpv_esimene,
    u"Viimase näidu aeg: %s" % kpv_utc,
    u"Näide oli: %d" % len(m),
    u"Keskmine näit: %.02f MW" % average
)

# Standardväljund
for rida in raporti_read:
    print rida

# HTML raport
with open("raport.html", "w", encoding="utf-8") as fh:
    fh.write("<html>")
    fh.write("<head>")
    fh.write("<meta charset='utf-8'>")
    fh.write("</head>")
    fh.write("<body>")
    fh.write("<h1>%s</h1>" % datetime.now())
    for rida in raporti_read:
        fh.write("<p>" + rida + "</p>")
    fh.write("</body>")
    fh.write("</html>")

# Tekstiraport
with open("raport.txt", "w", encoding="utf-8") as fh:
    for rida in raporti_read:
        fh.write(rida + "\r\n")

# Excel 2007
from openpyxl import Workbook
wb = Workbook()
ws = wb.active
ws.append([u"Esimene näit",  kpv_esimene])
ws.append([u"Vimane näit",   kpv_utc])
ws.append([u"Näitude arv",   len(m)])
ws.append([u"Keskmine näit", average])
wb.save("raport.xlsx")

Mitmest CSV failist ajatemplite järgi info kokku lappimine üheks CSV failiks:

# -*- coding: utf-8 -*-

import os
from glob import glob # Filename globbing
from datetime import datetime, timedelta

INPUT = "p*.csv"
OUTPUT = "merged.csv"

min_kpv = None
max_kpv = None
seosed = {}
headers = []

for filename in glob(INPUT):
    print u"Loen:", os.path.realpath(filename)
    with open(filename) as fh:
        basename = os.path.basename(filename)
        basename, extension = os.path.splitext(basename)
        headers.append(basename)
        for rida in fh:
            # Löö rida pooleks semikooloni järgi
            kpv, n2it = rida.split(";")

            # Parsi ajatempel
            kpv = datetime.strptime(kpv, "%d.%m.%Y %H:%M")

            # Nihuta min/max ajatemplit vajadusel
            if not max_kpv or kpv > max_kpv: max_kpv = kpv
            if not min_kpv or kpv < min_kpv: min_kpv = kpv

            # Seo ujukoma näit kuupäeva ja failinimega
            seosed[kpv, basename] = float(n2it)

print u"Kirjutan:", OUTPUT
kpv = min_kpv # Alusta minimaalsest kuupäevast
with open(OUTPUT, "w") as fh:
    fh.write("kpv;" + ";".join(headers)+ "\n")
    while kpv <= max_kpv:
        fh.write("%s;" % kpv)
        for basename in headers:
            try:
                fh.write("%.02f" % seosed[kpv,basename])
            except KeyError:
                pass
            fh.write(";")
        fh.write("\n")

        # Liida ajatemplile 5 minutit juurde
        kpv = kpv + timedelta(seconds=300)

        # Saaks ka nii:
        # kpv += timedelta(seconds=300)

Pisut kompaktsem näide kasutab csv moodulit mis hõlbustab natukene CSV failide töötlemist.

# -*- coding: utf-8 -*-

import os
import csv # CSV failide lugemise/kirjutamise moodul
from glob import glob # Filename globbing
from datetime import datetime, timedelta

INPUT = "p*.csv"
OUTPUT = "merged.csv"

min_kpv = None
max_kpv = None
seosed = {}
headers = []

for filename in glob(INPUT):
    print u"Loen:", os.path.realpath(filename)
    with open(filename) as fh:
        basename = os.path.basename(filename)
        basename, extension = os.path.splitext(basename)
        headers.append(basename)
        for kpv, n2it in csv.reader(fh, delimiter=";"):
            # Parsi ajatempel
            kpv = datetime.strptime(kpv, "%d.%m.%Y %H:%M")

            # Nihuta min/max ajatemplit vajadusel
            if not max_kpv or kpv > max_kpv: max_kpv = kpv
            if not min_kpv or kpv < min_kpv: min_kpv = kpv

            # Seo ujukoma näit kuupäeva ja failinimega
            seosed[kpv, basename] = float(n2it)

print u"Kirjutan:", OUTPUT
kpv = min_kpv # Alusta minimaalsest kuupäevast
with open(OUTPUT, "w") as fh:
    writer = csv.writer(fh, delimiter=";")
    writer.writerow(["kpv"] + headers)
    while kpv <= max_kpv:
        v2ljad = map(lambda basename:seosed.get((kpv,basename), ""), headers)
        writer.writerow([kpv] + v2ljad)
        kpv += timedelta(seconds=300)

Important

Python 2.x versioonides olev csv moodul väljastab baite, nii et vastava tähetabeli dekodeerimine tuleb eraldi realiseerida. Python 3.x väljalasetes säärast probleemi enam pole.