python vraagje ?

Alles over programmeren en development binnen de IT-wereld
Plaats reactie
Gebruikersavatar
broke23
Premium Member
Premium Member
Berichten: 560
Lid geworden op: 01 aug 2014, 10:28
Uitgedeelde bedankjes: 86 keer
Bedankt: 23 keer

heeft er iemand enig idee hoe ik een datum en tijd kan toevoegen in een file die ik probeer weg te schrijven ?

Code: Selecteer alles

file = open("/run/shm/em-"+format(serial)+"-"+format(value), "a")
                        file.write('%.4f' % emparts[value])
                        file.close()
geeft als output een waarde van mijn energiemeter, nu die energiemeter struurt geen datum en tijd mee ...

had iets geprobeerd in de zin van :

Code: Selecteer alles

file = open("/run/shm/em-"+format(serial)+"-"+format(value), "a")
			file.write('{%Y-%m-%d %H:%M:%S}'.format(datetime.datetime.now())+'%.4f' "\n" % emparts[value])
                        file.close()
maar dan schrijft het geen data meer weg,

ik zou een verwijzing ofzo kunnen definiëren maar heb echt geen idee, ik probeer de code te manipuleren naar eigen noden, maar zonder succes dus (paar dingen toch al gelukt, maar meer ook niet)

origineel komt van hier: https://github.com/datenschuft/SMA-EM/
elmariachi2920
Plus Member
Plus Member
Berichten: 174
Lid geworden op: 08 aug 2011, 17:09
Uitgedeelde bedankjes: 1 keer
Bedankt: 8 keer

wat gebeurt er als je "\n" verwijderd?
als je datum en de waardes op verschillende lijnen wilt hebben kan je evt het volgende proberen:

Code: Selecteer alles

file = open("/run/shm/em-"+format(serial)+"-"+format(value), "a")
file.write('{%Y-%m-%d %H:%M:%S}'.format(datetime.datetime.now()))
file.write('%.4f' % emparts[value])
file.close()
Gebruikersavatar
Didymus
Elite Poster
Elite Poster
Berichten: 1098
Lid geworden op: 17 jun 2004, 15:23
Uitgedeelde bedankjes: 258 keer
Bedankt: 94 keer

Probeer eens met:

Code: Selecteer alles

file.write(str(datetime.datetime.now()) + " " + '%.4f' "\n" % + emparts[value])
edit: Of in het format dat je zelf wou:

Code: Selecteer alles

file.write(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") + " " + "%.4f" % + emparts[value])
ubremoved_539
Deel van't meubilair
Deel van't meubilair
Berichten: 29849
Lid geworden op: 28 okt 2003, 09:17
Uitgedeelde bedankjes: 434 keer
Bedankt: 1972 keer

Je newline character staat op de verkeerde plaats.
Gebruikersavatar
Didymus
Elite Poster
Elite Poster
Berichten: 1098
Lid geworden op: 17 jun 2004, 15:23
Uitgedeelde bedankjes: 258 keer
Bedankt: 94 keer

Newline komt op de juiste plaats terecht, is volgens mij niet het probleem. Niet erg logisch/leesbaar, dat niet:

Code: Selecteer alles

In [151]: str(datetime.datetime.now()) + " " + '%.4f' "\n" % + 0.379234790345
Out[151]: '2017-12-06 16:20:38.731463 0.3792\n'
brubbel
Elite Poster
Elite Poster
Berichten: 918
Lid geworden op: 04 jul 2012, 16:55
Uitgedeelde bedankjes: 76 keer
Bedankt: 174 keer
Recent bedankt: 1 keer

import datetime

dt = datetime.datetime.now()
strDate = dt.replace(tzinfo=None).strftime("%Y%m%d%H%M%S")

https://docs.python.org/2/library/datet ... e-behavior
Gebruikersavatar
broke23
Premium Member
Premium Member
Berichten: 560
Lid geworden op: 01 aug 2014, 10:28
Uitgedeelde bedankjes: 86 keer
Bedankt: 23 keer

Didymus schreef:Probeer eens met:

Code: Selecteer alles

file.write(str(datetime.datetime.now()) + " " + '%.4f' "\n" % + emparts[value])
edit: Of in het format dat je zelf wou:

Code: Selecteer alles

file.write(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") + " " + "%.4f" % + emparts[value])

Code: Selecteer alles

File "sma-daemon.py", line 49
    file.write(datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") + " " + '%.4f' + % emparts[value])
                            ^
SyntaxError: invalid syntax
Zelfde met of zonder "\n"
Gebruikersavatar
Didymus
Elite Poster
Elite Poster
Berichten: 1098
Lid geworden op: 17 jun 2004, 15:23
Uitgedeelde bedankjes: 258 keer
Bedankt: 94 keer

Als je dit wil debuggen ga je best systematisch te werk:

Code: Selecteer alles

In [3]: datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
Out[3]: '2017-12-06 18:43:17'

In [4]: datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") + " "
Out[4]: '2017-12-06 18:43:24 '

In [5]: datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") + " " + '%.4f' 0.83039434
  File "<ipython-input-5-081ef786934f>", line 1
    datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") + " " + '%.4f' 0.83039434
                                                                                  ^
SyntaxError: invalid syntax

In [6]: datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") + " " + '%.4f' % 8.3983
Out[6]: '2017-12-06 18:43:55 8.3983'

In [7]: datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S") + " " + '%.4f' % 8.3983 + "\n"
Out[7]: '2017-12-06 18:46:02 8.3983\n'
Probleem is de positie van je %-teken dat na de + operator staat en daar geen betekenis heeft. Vervang gewoon de dummyvalue in mijn bv. door emparts[value]
gm123
Elite Poster
Elite Poster
Berichten: 1113
Lid geworden op: 08 maa 2009, 22:27
Uitgedeelde bedankjes: 63 keer
Bedankt: 116 keer

De properste manier om strings aan elkaar te zetten in python is als volgt.

Code: Selecteer alles

from datetime import datetime

tijd = datetime.now().strftime("%Y-%m-%d %H:%M");
value = 14.5 
string = "%s - %.4f \n" % (tijd, value)
print(string)
Het resultaat hiervan is:

Code: Selecteer alles

2017-12-06 19:42 - 14.5000 
Je definieert eerst het formaat van de string en je vult hem dan op. %s wordt gesubstitueerd door de string tijd en %.4f wordt gesubstitueerd door het kommagetal value. De volgorde van de substitutie is van links naar rechts, vandaar dat we (tijd, value) schrijven en niet (value, tijd) in dit voorbeeld. Verder kan je hier in schrijven wat je wil, je kan er ook iets van maken zoals

Code: Selecteer alles

string = "Op tijdstip %s verbruikte ik %.4f W \n" % (tijd, value)
In de variabele value steek je de waarde afkomstig van je energiemeter. In de variabele string zit vervolgens wat je moet wegschrijven naar je bestand. Enkel nog maar file.write(string) doen en klaar.

Als je niet zeker bent hoe het werkt gebruik je best altijd tussenvariabelen, dan kan je stap per stap debuggen indien je ergens een fout hebt. Het voorbeeld van hierboven is nu niet zo ingewikkeld, dus je kan ook evengoed het volgende schrijven (er vanuitgaande dat er een waarde in de variabele value zit), maar tussenvariabelen maken de boel direct een pak leesbaarder.

Code: Selecteer alles

file.write("%s - %.4f \n" % (datetime.now().strftime("%Y-%m-%d %H:%M"), value))
Gebruikersavatar
broke23
Premium Member
Premium Member
Berichten: 560
Lid geworden op: 01 aug 2014, 10:28
Uitgedeelde bedankjes: 86 keer
Bedankt: 23 keer

@gm123 en de rest

ik krijg alvast geen fouten meer met je laatste code gm123, maar de output geeft enkel de waarde van de energiemeter weer, dus GEEN datum EN de append modus valt precies weg met deze aanpassingen ? :?

Alvast bedankt voor de hulp, maar ik geraak er dus niet uit :bang:
Laatst gewijzigd door broke23 06 dec 2017, 20:15, in totaal 1 gewijzigd.
gm123
Elite Poster
Elite Poster
Berichten: 1113
Lid geworden op: 08 maa 2009, 22:27
Uitgedeelde bedankjes: 63 keer
Bedankt: 116 keer

En als je mijn eerste voorbeeld uitvoert, met gewoon die print? Krijg je dan wel een datum te zien? Print eens gewoon al je tussenvariabelen uit en kijk dan wat er misloopt. Schrijven naar een bestand doe je als allerlaatste, eerst debuggen met prints in de console. Zeker dat de waarde van je energiemeter een getal is?

De volgende code werkt hier:

Code: Selecteer alles

from datetime import datetime

tijd = datetime.now().strftime("%Y-%m-%d %H:%M");
value = 14.5 
string = "%s - %.4f \n" % (tijd, value)

f = open('test.txt', 'a+')
f.write(string)
f.close()
Resultaat na 4x uitvoeren:
Afbeelding
Gebruikersavatar
broke23
Premium Member
Premium Member
Berichten: 560
Lid geworden op: 01 aug 2014, 10:28
Uitgedeelde bedankjes: 86 keer
Bedankt: 23 keer

de waarde is idd een getal (met cijfers achter de komma)

dus als het werkt, print het altijd dat getal met cijfers achter de komma, maar niet meerdere onder elkaar dus

met je 1e voorbeeld:

Code: Selecteer alles

Traceback (most recent call last):
  File "sma-daemon.py", line 29, in <module>
    string = "%s - %.4f \n" % (tijd, value)
TypeError: a float is required
gm123
Elite Poster
Elite Poster
Berichten: 1113
Lid geworden op: 08 maa 2009, 22:27
Uitgedeelde bedankjes: 63 keer
Bedankt: 116 keer

broke23 schreef: de waarde is idd een getal (met cijfers achter de komma)
Blijkbaar niet! De error die je krijgt zegt letterlijk "a float is required". Hij verwacht dus dat 1 van je variabelen een float is. Er zit maar 1 float in die string, namelijk %.4f, wat wil zeggen dat je in de variabele value geen float hebt steken. Zeker dat je waarde geen kommagetal in de vorm van een string is? :)

Je kan het volgende proberen:

Code: Selecteer alles

string = "%s - %.4f \n" % (tijd, float(value))
Of indien het toch een string is:

Code: Selecteer alles

string = "%s - %s \n" % (tijd, value)
Maar het beste is misschien om het met format doen zoals je in jouw code al had geprobeerd. Dan heb je dat probleem niet met de types van je variabelen niet, python plakt dan automatisch het juiste type er in. Ik had het van in het begin ook zo moeten doen eigenlijk. Aangezien dit de 'nieuwe' manier is, de mijne is nog de 'oude'. :oops:

Code: Selecteer alles

string = "{} - {}".format(tijd, value)
Gebruikersavatar
broke23
Premium Member
Premium Member
Berichten: 560
Lid geworden op: 01 aug 2014, 10:28
Uitgedeelde bedankjes: 86 keer
Bedankt: 23 keer

Code: Selecteer alles

ValueError: could not convert string to float: 'emparts[value]'
dus ja, het zal dan een string zijn zeker :lol: het is een berekend getal: pregardcounter=hex2dec(smainfoasci[80:96])/3600000

soit, ik blijf proberen
gm123
Elite Poster
Elite Poster
Berichten: 1113
Lid geworden op: 08 maa 2009, 22:27
Uitgedeelde bedankjes: 63 keer
Bedankt: 116 keer

Dan zou mijn laatste stukje code wel moeten werken. Dat plakt gewoon de waarde van tijd en value integraal in de string op de plaats waar {} staat, python zorgt zelf voor de correcte typecasting. Ik zie dat je in jouw code ook de variabele 'value' gebruikt voor iets anders, die hergebruik je toch niet he? Want ik noem die variabele ook toevallig 'value' in mijn voorbeeldje, dat zijn 2 verschillende dingen natuurlijk.

Als het dan toch nog niet werkt dan zit er in je waarde afkomstig uit de meter toch echt wel iets meer dan gewoon een getal.
Gebruikersavatar
broke23
Premium Member
Premium Member
Berichten: 560
Lid geworden op: 01 aug 2014, 10:28
Uitgedeelde bedankjes: 86 keer
Bedankt: 23 keer

daarom dat ik dus nooit geen informatica ben gaan studeren hé, die kunde, of hoe dat ik het moet noemen, om te programmeren is er gewoon niet

Code: Selecteer alles

import sys, time
from datetime import datetime
from daemon3x import daemon3x
from configparser import SafeConfigParser
import smaem

tijd = datetime.now().strftime("%Y-%m-%d %H:%M:%S");
waarde = 'emparts[value]'
string = "{} - {} \n".format(tijd, waarde)

#read configuration
parser = SafeConfigParser()
parser.read('/etc/smaemd/config')

smaemserials=parser.get('SMA-EM', 'serials')
serials=smaemserials.split(' ')
smavalues=parser.get('SMA-EM', 'values')
values=smavalues.split(' ')
pidfile=parser.get('DAEMON', 'pidfile')

class MyDaemon(daemon3x):
        def run(self):
                emparts = {}
                while True:
                        emparts=smaem.readem()
                        for serial in serials:
                                #print(serial)
                                #print(emparts['serial'])
                                if serial==format(emparts['serial']):
                                        #print("match")
                                        for value in values:
                                                file = open("/run/shm/em-"+format(serial)+"-"+format(value),"a")
                                                file.write(string)
                                                file.close()
Dat heb ik er nu van gemaakt en dat logt dan als volgt:

Code: Selecteer alles

2017-12-06 21:06:59 - emparts[value] 
2017-12-06 21:06:59 - emparts[value] 
2017-12-06 21:06:59 - emparts[value]
dus het werkt inderdaad wel, maar ben toch ergens de mist in gegaan, want nu krijg ik dus mijn data van de energiemeter niet meer te zien (waarschijnlijk omdat ik mijn string ergens te vroeg invoeg ?) en dat tijdstip staat fixed precies ? dat loopt niet op ? (almost there denk ik ze)

denk niet dat je gezien hebt dat ik de waarde gepost heb hierboven :

Code: Selecteer alles

  pregardcounter=hex2dec(smainfoasci[80:96])/3600000
gm123
Elite Poster
Elite Poster
Berichten: 1113
Lid geworden op: 08 maa 2009, 22:27
Uitgedeelde bedankjes: 63 keer
Bedankt: 116 keer

Dat is niet je volledige code veronderstel ik? Maar ik denk dat ik het zie.

Allereerst vervang

Code: Selecteer alles

waarde = 'emparts[value]'
door

Code: Selecteer alles

waarde = emparts[value]
In het eerste geval plak je letterlijk de woorden 'emparts[value]' in je string. Je wil natuurlijk de waarde uit de variabele emparts[value] opvragen, dit doe je zonder quotes. Als je nog zo'n basic fouten maakt raad ik je aan om toch eerst nog wat python tutorials te volgen alvorens je dit soort projectjes doet, daar hoef je zeker niet voor gestudeerd te hebben, er zijn op internet genoeg tutorials voor beginners te vinden die een overzicht van alle basis geven. Niet slecht bedoeld hé, maar dit is echt de basis van de basis en je moet toch wel een beetje weten wat je aan het doen bent.

Vervolgens kan je tijd, waarde en string pas definiëren op de plaats in je code waar je effectief de meetwaarde uitleest, dit is net boven de plaats waar je file.write() doet. Als ik het goed heb moet het dus zo zijn.

Code: Selecteer alles

import sys, time
from datetime import datetime
from daemon3x import daemon3x
from configparser import SafeConfigParser
import smaem

#read configuration
parser = SafeConfigParser()
parser.read('/etc/smaemd/config')

smaemserials=parser.get('SMA-EM', 'serials')
serials=smaemserials.split(' ')
smavalues=parser.get('SMA-EM', 'values')
values=smavalues.split(' ')
pidfile=parser.get('DAEMON', 'pidfile')

class MyDaemon(daemon3x):
        def run(self):
                emparts = {}
                while True:
                        emparts=smaem.readem()
                        for serial in serials:
                                #print(serial)
                                #print(emparts['serial'])
                                if serial==format(emparts['serial']):
                                        #print("match")
                                        for value in values:
                                                file = open("/run/shm/em-"+format(serial)+"-"+format(value),"a")
                                                tijd = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
                                                waarde = emparts[value]
                                                string = "{} - {} \n".format(tijd, waarde)
                                                file.write(string)
                                                file.close()
Gebruikersavatar
broke23
Premium Member
Premium Member
Berichten: 560
Lid geworden op: 01 aug 2014, 10:28
Uitgedeelde bedankjes: 86 keer
Bedankt: 23 keer

HALLELUJA :banana:

dikke merci gm123!!!! :beerchug:

Code: Selecteer alles

2017-12-06 21:32:20 - 203.6328 
2017-12-06 21:32:21 - 203.6329 
2017-12-06 21:32:22 - 203.6329 
2017-12-06 21:32:23 - 203.633 
2017-12-06 21:32:24 - 203.6331 
2017-12-06 21:32:25 - 203.6332 
2017-12-06 21:32:26 - 203.6333 
2017-12-06 21:32:27 - 203.6334 
Hen specifiek gezocht naar info van wat ik nodig had maar denk dat ik te vaak of foute terminologie gezocht heb
fujiwara
Starter
Starter
Berichten: 15
Lid geworden op: 29 sep 2014, 13:06
Bedankt: 2 keer

Die orginele code ziet er niet echt proper geschreven uit moet ik zeggen. Welke versie van Python wordt er hier gebruikt trouwens?
Met wat aanpassingen kan het een stuk duidelijker geschreven worden:

Code: Selecteer alles

import sys, time
from datetime import datetime

from daemon3x import daemon3x
from configparser import ConfigParser
import smaem

CONFIG_FILE_PATH = '/etc/smaemd/config'


def read_config(config_file_path):
    #read configuration
    parser = ConfigParser()
    parser.read('/etc/smaemd/config')

    smaemserials=parser.get('SMA-EM', 'serials')
    serials=smaemserials.split(' ')
    smavalues=parser.get('SMA-EM', 'values')
    values=smavalues.split(' ')
    pidfile=parser.get('DAEMON', 'pidfile')
    return (pidfile, serials, values)

class MyDaemon(daemon3x):

    def __init__(self, pid_file, sma_serials, sma_value_types):
        super(MyDaemon, self).__init__(pid_file)
        self.sma_serials = sma_serials
        self.sma_value_types = sma_value_types

    def run(self):
        while True:
            # Read the emparts & get the current time since that is the timestamp of the data
            emparts = smaem.readem()
            now = datetime.now()
            # Only write the data if it has the requested serial
            sma_serial = str(emparts.get('serial'))
            if sma_serial in self.sma_serials:
                for sma_value_type in self.sma_value_types:
                    with open("/run/shm/em-{}-{}".format(sma_serial, sma_value_type),"a") as fh:
                        fh.write("{:%Y-%m-%d %H:%M:%S} - {}\n".format(now, emparts.get(sma_value_type, "NA")))


if __name__ == "__main__":
    pidfile, serials, values = read_config(CONFIG_FILE_PATH)
    daemon = MyDaemon(pidfile, serials, values)

    if len(sys.argv) == 2:
        if 'start' == sys.argv[1]:
            daemon.start()
        elif 'stop' == sys.argv[1]:
            daemon.stop()
        elif 'restart' == sys.argv[1]:
            daemon.restart()
        else:
            print ("Unknown command")
            sys.exit(2)
        sys.exit(0)
    else:
        print("usage: %s start|stop|restart" % sys.argv[0])
        print(pidfile)
sys.exit(2)

Code: Selecteer alles

sma_serial = str(emparts.get('serial'))
if sma_serial in self.sma_serials:
   ...
De serial die je krijgt is in integer formaat. De normale manier om deze om te zetten in een string is de 'str()' functie te gebruiken. Snap niet waarom ze format() gebruiken zonder een format specifier dan nog.
Daarnaast gebruik je best de get() functie om de waardes uit de dict te lezen. Dit voorkomt dat je KeyError exception kan krijgen moest er iets ontbreken in de uitgelezen data.
Vermits er enkel wordt gekeken of de serial van de uitgeleesde data in de geconfigureerde serials zit, kan beter de 'in' constructie gebruikt worden.

Code: Selecteer alles

"{:%Y-%m-%d %H:%M:%S} - {}\n".format(now, emparts.get(sma_value_type, "NA"))
Je kan met de format functie rechtstreeks de date formatting gebruiken. Het tweede argument van de get functie geeft je een default waarde terug indien de key niet in de dict wordt gevonden.

Code: Selecteer alles

with open("/run/shm/em-{}-{}".format(sma_serial, sma_value_type),"a") as fh:
   ...
Ook wordt het beste de 'with' constructie gebruikt om bestanden te openen. Dit zorgt ervoor dat de file altijd gesloten wordt ook in het geval van exceptions. Deze functie is wel niet in alle Python versies beschikbaar.

PS. Deze code is niet getest dus kan nog fouten bevatten :-)
Gebruikersavatar
broke23
Premium Member
Premium Member
Berichten: 560
Lid geworden op: 01 aug 2014, 10:28
Uitgedeelde bedankjes: 86 keer
Bedankt: 23 keer

@fujiwara, je code net even getest omdat ik wat aan het prullen was om iets nieuw te implementeren, en je code werkt :beerchug:

nu nog uitvogelen hoe ik de creatie van die file limiteer per dag
Plaats reactie

Terug naar “Development”