Kakebakelate Skrevet 29. april 2014 Del Skrevet 29. april 2014 (endret) 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 30. april 2014 av Runarbs Lenke til kommentar
zotbar1234 Skrevet 29. april 2014 Del Skrevet 29. april 2014 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
Kakebakelate Skrevet 29. april 2014 Forfatter Del Skrevet 29. april 2014 (endret) 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 30. april 2014 av Runarbs Lenke til kommentar
etse Skrevet 30. april 2014 Del Skrevet 30. april 2014 (endret) 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 30. april 2014 av etse Lenke til kommentar
Kakebakelate Skrevet 30. april 2014 Forfatter Del Skrevet 30. april 2014 (endret) 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 30. april 2014 av Runarbs Lenke til kommentar
zotbar1234 Skrevet 30. april 2014 Del Skrevet 30. april 2014 Er det feil å skrive det på følgende måte? Ja. Søk etter "sql injection". Lenke til kommentar
zotbar1234 Skrevet 30. april 2014 Del Skrevet 30. april 2014 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
etse Skrevet 30. april 2014 Del Skrevet 30. april 2014 (endret) 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 formattingHar 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 30. april 2014 av etse Lenke til kommentar
Foxboron Skrevet 1. mai 2014 Del Skrevet 1. mai 2014 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
zotbar1234 Skrevet 1. mai 2014 Del Skrevet 1. mai 2014 (endret) 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 1. mai 2014 av zotbar1234 1 Lenke til kommentar
Kakebakelate Skrevet 2. mai 2014 Forfatter Del Skrevet 2. mai 2014 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
snippsat Skrevet 2. mai 2014 Del Skrevet 2. mai 2014 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å. 90% var da høyt når dette er helt klart metoden man bruker for og kun lese linje for linje til minnet Lenke til kommentar
Anbefalte innlegg
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 kontoLogg inn
Har du allerede en konto? Logg inn her.
Logg inn nå