Gå til innhold

Anbefalte innlegg

Hei.

Jeg driver å skriver et lite program som skal hente sensordata fra en tekstfil. Problemet er at det kan bli snakk om opp til en milion liner med data. Noe som fører til at Raspberryen og databasen tok kveld. Det jeg lurer på om jeg trenger er en mer effektiv måte når jeg splitter hver linje fra hverandre. Siden jeg skal filterere dataene også lurer jeg på om jeg kanskje burde brukte Numpy .

Men det mener jeg at jeg har en tabell for Ax, Ay, Az, Gx, Gy, Gz.

 

 

import math
import _mysql
import sys
import time
import os
import MySQLdb
import numpy

# Setup mysql

# Open database connection
db = MySQLdb.connect("localhost","pi",'Ankerfast','dsa' )

# prepare a cursor object using cursor() method
cursor = db.cursor()

# gives all the values from the same drop same id (aid).
cursor.execute("select aid from data order by id desc limit 1")
row = cursor.fetchone()
if row is None:
    aid = 1
else:
    aid = row[0]+1
aid = str(aid)

# Sets path to file and list whats in the directory

#path = "/media/usb0/"
path ="/var/www/pythonprogram/"
#asd =os.path.abspath("/media/usb0/tilfeldigetall.txt")
asd = os.path.abspath("/var/www/pythonprogram/tilfeldigetall.txt")
dirs = os.listdir(path)

# unix time stamp
timestamp = int(time.time())
depth = 0
###
window = 11
samplerate = 800
"""
def average(arr,n):
    end n*int(len(arr(n)
    return numpy.mean(arr[:end].reshape(-1,n),1)
"""

# Reads the file and append the angle to

depthfailcounter = 0

#with open(asd, 'r') as f: # Opens file and reads it
#    rawData = f.readlines()
with open('tilfeldigetall.txt') as rawData:
    #
    #for x in range(1000):
        for line in rawData:
            dataSplit = line.split()
            """ax = dataSplit[0]
            ay = dataSplit[1]
            az = dataSplit[2]
            gx = dataSplit[3]
            gy = dataSplit[4]
            gz = dataSplit[5]
            
            Array = numpy.array([])
            
            try:
                Ax = numpy.append(Ax,ax)
            except ValueError:
                Ax.append('999')
            print Ax                            
            """            
            try:
                Ax = float(dataSplit[0])    
            except ValueError:
                Ax = dataSplit[0]
                Ax = '999'
                
            try:
                Ay = float(dataSplit[1])
            except ValueError:
                Ay = dataSplit[1]
                Ay = '999'
                
            try:
                Az = float(dataSplit[2])    
            except ValueError:
                Az = dataSplit[2]
                Az = '999'
                
            try:
                Gx = float(dataSplit[3])
            except ValueError:
                Gx = dataSplit[3]
                Gx = '999'
                
            try:
                Gy = float(dataSplit[4])
            except ValueError:
                Gy = dataSplit[4]
                Gy = '999'
                
            try:
                Gz = float(dataSplit[5])
            except ValueError:
                Gz = dataSplit[5]
                Gz = '999'
            """
            filterX.append(Ax)
            weighted = numpy.repeat(1.0/window)/window
            numpy.convolve(filterX, weighted)[window-1:-(window-1)]
            """        
            #signal.order_filter
            # caluate angle of anchor from acc            
            if Ax == '999' or Ay == '999' or Az =='999':
                AanchorAngle = '999'
            else:
                delta = (Az/((Ax*Ax)+(Ay*Ay)))
                AanchorAngle = math.atan(delta)
                AanchorAngle =math.degrees(AanchorAngle)
                #print AanchorAngle
                AanchorAngle = abs(AanchorAngle)
            # calcuate angle from gyro
            if Gx == '999' or Gy == '999' or Gz =='999':
                GanchorAngle = '999'
            else:
                Gdelta = (Gz/((Gy*Gy)+(Gx*Gx)))
                GanchorAngle = math.atan(Gdelta)
                GanchorAngle = math.degrees(GanchorAngle)
                GanchorAngle = abs(GanchorAngle)
                
            if Az == '999':    
                depth +=AzOld*(1.0/samplerate)
                depthfailcounter += depthfailcounter
            else:
                depth +=Az*(1.0/samplerate)

            AzOld = Az

            #populate mysql database
            cursor.execute("insert into data(aid, x, y,z, ang, gx, gy, gz, gang, time) values ('%s','%s','%s','%s','%s','%s','%s','%s','%s','%s')" % (aid, Ax, Ay, Az, GanchorAngle, Gx, Gy, Gz, AanchorAngle, timestamp))        
        db.commit() # write the changes to the db
        
cursor.execute("insert into anchors(aid, ang, dep, time) Values('%s','%s','%s','%s')" %(aid, AanchorAngle, depth, timestamp))
db.commit() # write the changes to the db
db.close() #disconnect the mysql server

 

 

Endret av Runarbs
Lenke til kommentar
Videoannonse
Annonse

Jeg driver å skriver et lite program som skal hente sensordata fra en tekstfil. Problemet er at det kan bli snakk om opp til en milion liner med data. Noe som fører til at Raspberryen og databasen tok kveld.

Eksakt hva betyr "tok kveld"?

 

Det jeg lurer på om jeg trenger er en mer effektiv måte når jeg splitter hver linje fra hverandre.

 

 

depthfailcounter = 0
with open('tilfeldigetall.txt') as rawData:
    for x in range(0,101):
        for line in rawData:
            # ... 

    cursor.execute("INSERT INTO data(aid,x,y,z,ang,gx,gy,gz,gang,time) Values('"+aid+"', '"+Ax+"', '"+Ay+"', '"+Az+"', '"+GanchorAngle+"', '"+Gx+"', '"+Gy+"', '"+Gz+"','"+AanchorAngle+"' , '"+timestamp+"')")

    db.commit() # write the changes to the db

depth = str(depth)
cursor.execute("insert into anchors(aid, ang, dep, time) Values('"+aid+"', '"+AanchorAngle+"', '"+depth+"', '"+timestamp+"')")

 

Mm... hvordan er denne koden tiltenkt å virke?

 

* for x in range()-linjen er meningsløs (ved siden av det kan man skrive range(101) for å oppnå det samme), fordi innmaten eksekveres eksakt 1 gang dersom man lykkes å åpne filen

* du eksekverer 1 insert(), hvis innhold er verdiene fra den siste linjen i filen. Er det meningen?

* å konvertere verdiene til StringType for å bake dem inn i insert()-setningen er bare be om problemer. Bruk place holders/frie variable.

* Uttrykk som 'math.degrees(AanchorAngle)' slik de står i koden din gir ikke mening.

* Kan du poste det minste fungerende eksempelet som illustrerer både hva du prøver å oppnå og hva du faktisk får til?

* Kan du komprimere eksempelet til noe som

Lenke til kommentar

Raspberryen sto i omlag 40 minutter med 100 cpuforbruk og minneforbruk og reagerte ikke på andre kommandoer. Hele koden kom vist ikke med, så har fikset det nå. Samt fikset formatering, likte vist ikke overgangen fra Geany til diskusjon.no

 

for in range var for å prøve og se om databasen hengde seg pga for mange filer ble skrevet til den.

punkt nr 2 er jeg ikke helt sikker på hva du mener med.

MySQL nektet å ta i mot verdiene så fremst jeg ikke casted det til string, ikke noe jeg ønsket men det var kun det den fungerte.

 

Koden fungerer, men problemet er hvis tekstfilen som skal leses blir for stor vil det skape problemer for raspberryen når dataen skal legges over til mysql-databasen.

.Det skal sies at jeg kan særdeles lite om Python og har stort sett bare erfaring med C-programering til mikrokontrollere så dette er ganske nytt for meg.

 

Edit: Forsøkte på nytt med mysql, fikk fjernet problemet med som gjorde at jeg ikke fikk sendt dataen til databasen så fremst det ikke var string. Rett og slett bare noobing fra min side. Du hadde også rett i at degree ikke gav noe meining.

Endret av Runarbs
Lenke til kommentar

cursor.execute("insert into anchors(aid, ang, dep, time) Values('"+aid+"', '"+AanchorAngle+"', '"+depth+"', '"+timestamp+"')")
Det der er feil måte å gjøre ting på - og av en eller annen grunn er det mange guides som lærer folk å gjøre det på den måten. (ofte folk som har lest dårlige PHP-totorials hvor de ikke tar for seg prepared statements o.s.v.).

 

Måten du vil gjøre dette på er:

cursor.execute("insert into anchors(aid, ang, dep, time) Values(?, ?, ?, ?)", (aid, AnchorAngle, depth, timestamp))
Følgende kode gir ikke mening (den gjør ingenting)

else:
    delta = Az/(Ax*Ax+Ay*Ay)
    AanchorAngle = math.atan(delta)
    math.degrees(AanchorAngle)
    abs(AanchorAngle)
Tenker deg på math.degrees og abs. Du tar aldri vare på resultatene, tenkte du egentlig at dette skulle være:

else:
    delta = Az/(Ax*Ax+Ay*Ay)
    AanchorAngle = math.atan(delta)
    AanchorAngle = math.degrees(AanchorAngle)
    AanchorAngle = abs(AanchorAngle)
Endret av etse
Lenke til kommentar

Er det feil å skrive det på følgende måte?

cursor.execute("insert into anchors(aid, ang, dep, time) Values('%s','%s','%s','%s')" %(aid, AanchorAngle, depth, timestamp))

Koden over fungerer men hvis jeg bruker ? istedenfor '%s' så får jeg bare opp feilmelding.

TypeError: not all arguments converted during string formatting

Har oppdatert koden i førsteposten

Endret av Runarbs
Lenke til kommentar

Litt lettere å kommentere nå, selv om "minimalt eksempel" var det ikke.

 

# gives all the values from the same drop same id (aid).
cursor.execute("select aid from data order by id desc limit 1")
row = cursor.fetchone()
if row is None:
    aid = 1
else:
    aid = row[0]+1
aid = str(aid)
Helt klart problematisk hvis flere oppdateringer kjøres i parallell, men akk og ve...

 

with open('tilfeldigetall.txt') as rawData:
        for line in rawData:
            dataSplit = line.split()
            try:
                Ax = float(dataSplit[0])    
            except ValueError:
                Ax = dataSplit[0]
                Ax = '999'

            cursor.execute("insert into data(aid, x, y,z, ang, gx, gy, gz, gang, time) values ('%s','%s','%s','%s','%s','%s','%s','%s','%s','%s')" % (aid, Ax, Ay, Az, GanchorAngle, Gx, Gy, Gz, AanchorAngle, timestamp))        

        db.commit() # write the changes to the db
Det kan være en ide å kjøre commits() oftere enn 1 gang per fil. Raspberry sliter opplagt med ressurser for å ha alle radene i en midlertidig tabell for å gjøre committen atomisk. Jeg ville ha testet med en fil på 1/10 av plassen for å finne ut hvor tiden forsvinner, men det skulle ikke forundre meg om det var i commit().

 

for in range var for å prøve og se om databasen hengde seg pga for mange filer ble skrevet til den.

for-in-range-konstruksjonen din i forrige versjon gav ingen mening, da innmaten i den løkken ble eksekvert høyst 1 gang (trivia: hvorfor?)

 

punkt nr 2 er jeg ikke helt sikker på hva du mener med.

Eksakt det jeg mente. I den forrige versjonen eksekverte man (høyst) 1 insert(), hvis innhold er verdiene fra den siste linjen i filen.

 

MySQL nektet å ta i mot verdiene så fremst jeg ikke casted det til string, ikke noe jeg ønsket men det var kun det den fungerte.

 

Det er beviselig feil (jfr. innlegget til etse).

 

Koden fungerer ...

Nuvel.

 

men problemet er hvis tekstfilen som skal leses blir for stor vil det skape problemer for raspberryen når dataen skal legges over til mysql-databasen.

1) profiler koden. Finn ut hvor tiden forsvinner med stadig større filer.

2) hvis det er rundt commit(), så må du stykke opp transaksjonen din. Forhåpentligvis byr det ikke på problemer. Kjør en commit() for hvert x*10^N rad for en passende verdi av x og N.

Lenke til kommentar

Er det feil å skrive det på følgende måte?

cursor.execute("insert into anchors(aid, ang, dep, time) Values('%s','%s','%s','%s')" %(aid, AanchorAngle, depth, timestamp))
Koden over fungerer men hvis jeg bruker ? istedenfor '%s' så får jeg bare opp feilmelding.

TypeError: not all arguments converted during string formatting
Har oppdatert koden i førsteposten

 

Du husket å dele spørringen fra argumentene med komma, i stede for prosent-tegn? cursor.execute() er en kommando som tar inn 2 argumenter. De førate argumentet er selve spørringen din som en streng, mens den andre argumentet er en tuple/liste med argumenter som skal brukes i spørringen. (hvor de byttes ut med prosenttegnet)

 

Eksempel på riktige måter å utføre spørringer:

cursor.execute("SELECT * FROM users WHERE username=? AND password=?", (username, password))

cursor.execute("INSERT INTO users(username, password) VALUES(:who, :secret)", {"who": username, "secret": password})
Endret av etse
Lenke til kommentar

Problemet er at han åpner og leger hele fila i minnet, noe som er en litt ugrei ting å gjøre om fila inneholder et par millioner linjer.

 

Det lureste da er å lese en og en linja fra fila for å unngå å lese alt inn i minnet.

with open(tilfeldigetall.txt') as rawData:
    for line in rawData.readline():
        # kode

Jeg er 90% sikker på at om du skriver kun `for line in rawData` så leses hele fila til minnet, men det kan noen korrigere meg på.

Lenke til kommentar

Jeg er 90% sikker på at om du skriver kun `for line in rawData` så leses hele fila til minnet, men det kan noen korrigere meg på.

Dette er feil (fileobject.c:file_iternext(), f.eks).

 

Faktisk ser CPython til å optimalisere for line in file(...).readlines()-konstruksjonen også. Holder man referansen til linjene eksplisitt, skjer dette:

 

$ python readline.py /tmp/bigfile.txt 
before loop: heap size 3322512
inner loop 1, heap size 3083200
inner loop 1, heap size 3083120
(...)
after loop: heap size 3083144
inner loop 2, heap size 1126992680
inner loop 2, heap size 1126992760
... der selve snutten itererer over samme fil vha:

 

seq = file(sys.argv[1])
for line in seq:
    # ... 

seq = file(sys.argv[1]).readlines()
for line in seq:
    # ... 
Meningen med next()-metoden for FileObject er nettopp å slippe å tenke på at filene kan være store. Minneforbruket skal ikke overstige den maksimale linjelengden vesentlig, uavhengig av filstørrelsen.

 

Jeg tviler forresten på at

 

 

with open(tilfeldigetall.txt') as rawData:
    for line in rawData.readline():
        # kode

 

... har ønsket effekt.

Endret av zotbar1234
  • Liker 1
Lenke til kommentar

Tusen takk for svarene hittil de har vært veldig hjelpsome. Men det ser ut som at jeg må skrive om vesentlige deler av scriptet grunnet at nettsiden slik den er pr dags dato potsensielt kan dø (et eller at med javascriptarray som ble for stort) . Så jeg kommer nok snart tilbake med ny kode og mindre lure spørsmål.

Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
  • Hvem er aktive   0 medlemmer

    • Ingen innloggede medlemmer aktive
×
×
  • Opprett ny...