Speichern in Datei innerhalb von Endlosschleife

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Dexter
User
Beiträge: 10
Registriert: Freitag 10. Januar 2014, 03:44

Hi und Hallo,

ich bin noch relativ neu in der Pythonwelt. Habe jetzt nach sehr vielem herumprobieren mich doch entschlossen hier einmal nachzufragen. Folgendes Problem:
Ich habe mir dieses klitzkleine Script gebaut:

Code: Alles auswählen

#!/usr/bin/env python2.7  
 
import RPi.GPIO as GPIO  
GPIO.setmode(GPIO.BCM)  

while True:
   # GPIO 23 set up as input. It is pulled up to stop false signals  
   GPIO.setup(23, GPIO.IN, pull_up_down=GPIO.PUD_UP)  
  
   print "Make sure you have the camera connected so that when a signal comes"  
   print "it will connect GPIO port 23 (pin 16) to GND (pin 6)\n"  
   #raw_input("Press Enter when ready\n>")  
  
   print "Waiting for voltage drop on port 23\n"  
   # program is waiting for falling edge 

   try:  
       GPIO.wait_for_edge(23, GPIO.FALLING)  
	   if GPIO.IN == True:
          f = open('interrupt', 'w')
          f.write('Voltage drop detected, getting GPS-Time\n') 
		  #f.flush()
          f.close()

   except KeyboardInterrupt:  
       GPIO.cleanup()       # clean up GPIO on CTRL+C exit  
   GPIO.cleanup()           # clean up GPIO on normal exit 
Es liest einen Spannungsabfall einer an PIN 23 (RaPi GPIO) angeschlossenen Elektronik aus. Der Spannungsabfall wird auch wie gewünscht erkannt. Nur hat sich das Programm nach dem ersten Durchlauf immer beendet. Deswegen die infinte Schleife zu Beginn des Codes. Jetzt kann ich wie gewünscht immer wieder den Interrupt auslösen. Weiter unten will ich dann das (erstmal testweise) die Zeile "Voltage drop detected, getting GPS-Time" in ein Textfile geschrieben wird. Allerdings wird nur eine eizige Zeile in das Textfile geschrieben und nicht wie gewünscht die Anzahl an Zeilen, die der Anzahl Interrupts entspricht. Ich habe alle möglichen Schleifenkonstruktionen, Abfragen mit allen möglichen Varaiblen ausprobiert. Komme aber nicht auf ein zufriedenstellendes Ergebnis!

Vielleicht kann mir einer von euch einen Denkanstoss geben?

ps.: Der Code ist mit Sicherheit nicht schön, aber er funktioniert im Kern. Bin ja noch blutiger Anfänger :P

Grüße
Dexter
Dexter
User
Beiträge: 10
Registriert: Freitag 10. Januar 2014, 03:44

Okay Epic Fail!

Die Datei wird natürlich immer wieder überschrieben, da sie innerhalb der while Schleife erstellt wird. Habe das erstellen der Datei über die While schleife verschoben. Nun funzt es!

Edit: Dafür funktioniert mein weiteres vorgehen nicht. Ich habe nun den Code:

Code: Alles auswählen

#!/usr/bin/env python2.7  
 
import RPi.GPIO as GPIO  
GPIO.setmode(GPIO.BCM)  

f = open('interrupt.txt', 'w')
f2 = open('gps.txt', 'r')

while True:
   # GPIO 23 set up as input. It is pulled up to stop false signals  
   GPIO.setup(23, GPIO.IN, pull_up_down=GPIO.PUD_UP)  
  
   print "Make sure you have the camera connected so that when a signal comes"  
   print "it will connect GPIO port 23 (pin 16) to GND (pin 6)\n"  
   #raw_input("Press Enter when ready\n>")  
  
   print "Waiting for voltage drop on port 23\n"  
   # program is waiting for falling edge 

   try:  
       GPIO.wait_for_edge(23, GPIO.FALLING)  
	   if GPIO.IN == True:
          f.write('Voltage drop detected, getting GPS-Time\n')
          f.flush()
	   
   except KeyboardInterrupt:  
       GPIO.cleanup()       # clean up GPIO on CTRL+C exit  
   GPIO.cleanup()           # clean up GPIO on normal exit 
Nun möchte ich aber mit f.write() nicht mehr den einen Satz schreiben, sondern eine einzelne Zeile, die ich aus einem anderen Textdokument lesen möchte. Das habe ich über diesen Code versucht, bekomme aber irgendwie unergründliche Syntax Errors:

Code: Alles auswählen

# Datei file einlesen
def readfile(file):
	f = codecs.open(file, 'r', 'utf-8')
	lines = list()
	try:
		for line in f:
			lines.append(line.strip())
	finally:
		f.close()
	return lines

# Den Inhalt von data in file schreiben
def writefile(file, data):
	f = codecs.open(file, 'w', 'utf-8')
	for line in data:
		f.write(line)
		f.write('\n')
	f.close()


Das habe ich in meinen Code in die if-Schleife eingefügt, komme jedoch nichtmal zum auslesen, da ich indent und Syntax Fehler bekomme. Diese kann ich aber patu nicht entdecken.

Gibt es vielleicht eine einfachere Möglichkeit eine Zeile aus einem txt auszulesen und diese bei jedem Interrupt in ein anderes txt zu schreiben?
p90
User
Beiträge: 198
Registriert: Donnerstag 22. Juli 2010, 17:30

Hm zwei Fragen:
1. Dein GPIO Setup und Cleanup ist in der Schleife, soll das wirklich mit jeder Schleife ausgeführt werden?
2. Solltest du "with" zum öffnen der Datei benutzen. Du flushsd zwar aber trotzdem.

[EDIT]
Geht das in die Richtung was du machen willst?

Code: Alles auswählen

#!/usr/bin/env python2.7  

import RPi.GPIO as GPIO  
GPIO.setmode(GPIO.BCM)  

# Datei file einlesen
def readfile(file_path):
    with codecs.open(file_path, 'r', 'utf-8') as file:
        return file.readlines()

# Den Inhalt von data in file schreiben
def writefile(file_path, data):
    with codecs.open(file_path, 'a', 'utf-8') as file:
        #using a for append, if w, the file will only containg
        #the last written line
        file.writelines(data)
        #data must be some kind of sequence like a list

while True:
    # GPIO 23 set up as input. It is pulled up to stop false signals  
    GPIO.setup(23, GPIO.IN, pull_up_down=GPIO.PUD_UP)  
    print "Make sure you have the camera connected so that when a signal comes"  
    print "it will connect GPIO port 23 (pin 16) to GND (pin 6)\n"  
    #raw_input("Press Enter when ready\n>")  
    print "Waiting for voltage drop on port 23\n"  
    # program is waiting for falling edge
    try:
        GPIO.wait_for_edge(23, GPIO.FALLING)  
        if GPIO.IN == True:
            #interrupt.write('Voltage drop detected, getting GPS-Time\n')
            #interrupt.flush()
            #read gps.txt and append content to interrupt.txt
            writefile("interrupt.txt", readfile("gps.txt"))
    finally:
        GPIO.cleanup() # always clean GPIO
Zuletzt geändert von p90 am Freitag 10. Januar 2014, 08:10, insgesamt 1-mal geändert.
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Oha... Dein ``readfile`` ließe sich viel hübscher so ausdrücken:

Code: Alles auswählen

def readfile(filename):
    with codecs.open(filename, 'r', 'utf-8') as f:
        return [line.strip() for line in f]
Im übrigen solltest Du nicht ``file`` als Namen verwenden. Erstens überschreibst Du damit ein Builtin und zweitens passt der Name nicht zum Objekt dahinter: Du übergibst eben *kein* File-Objekt, sondern einen *Dateinamen*!

Und bitte verwende doch vier Leerzeichen als Einrückung - wie es PEP8 vorsieht.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Dexter
User
Beiträge: 10
Registriert: Freitag 10. Januar 2014, 03:44

@p90 Das sieht schon sehr gut aus. Auch wenn ich den Code genauer studieren und zu einigen der Bausteinen in die Beschriebungen gucken muss um komplett durchzusteigen. Aber ich will es ja schließlich auch lernen und nicht nur einen vorgekauten Code verwenden. Danke aber auf jeden Fall schonmal. Kann es leider am Montag erst testen, aber werde mich dann wieder melden.

@Hyperion Ich verwende nicht "file" in meinem Programm. Das habe ich lediglich zum einfacheren lesen des Codes dort eingefügt. :wink:
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Dexter hat geschrieben: @Hyperion Ich verwende nicht "file" in meinem Programm. Das habe ich lediglich zum einfacheren lesen des Codes dort eingefügt. :wink:
Ersteres ist gut, letzteres nicht, denn ``filename`` hätte sich eben einfacher gelesen, da man nicht auf die falsche Fährte gelockt wird.
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
Dexter
User
Beiträge: 10
Registriert: Freitag 10. Januar 2014, 03:44

P90, das Skript funktioniert soweit super, außer das ich noch codecs importieren musste :P
Es tun sich aber immer neue Probleme auf...Ich möchte jedes mal wenn eine der Zeilen geschrieben wird, die entsprechende Zeilennummer davor geschrieben wird. Am besten sollte das in der ersten Spalte stehen und das was aus der anderen Datei geholt wurde in die zweite. Bekomme das allerdings nicht hin und google spuckt absolut nichts in die Richtung aus.
Ich meine es kann ja nicht so schwer sein eine extra Spalte einzufügen und in diese eine fortlaufende Zahl einzufügen. Gibt es da vielleicht eine extra Funktion?
Dexter
User
Beiträge: 10
Registriert: Freitag 10. Januar 2014, 03:44

Da ich meinen Beitrag anscheinend nicht editieren kann...
Hab es hinbekommen, jetzt sieht die Datei schön aus! Aber meine nächste Frage kommt bestimmt bald, wenn ihr nichts dagegen habt. :P
Benutzeravatar
Hyperion
Moderator
Beiträge: 7478
Registriert: Freitag 4. August 2006, 14:56
Wohnort: Hamburg
Kontaktdaten:

Dexter hat geschrieben: Ich meine es kann ja nicht so schwer sein eine extra Spalte einzufügen und in diese eine fortlaufende Zahl einzufügen. Gibt es da vielleicht eine extra Funktion?
Auch wenn Du es vermutlich schon gelöst hast: ``enumerate`` ist die Funktion, die Du suchst (gesucht hast) ;-)
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
carsten171263
User
Beiträge: 4
Registriert: Montag 16. Dezember 2013, 17:01

in Zeile 20 mußt Du statt f = open('interrupt', 'w') folgendes eintragen: f = open('interrupt', 'a'). Das a hinten steht für auf deutsch anfügen (append).

cu, Carsten
Dexter
User
Beiträge: 10
Registriert: Freitag 10. Januar 2014, 03:44

Du meinst wohl Zeile 6?!

Ich habe heute nochmal meinen Quelltext ausgeführt. Er hat vor zwei Tagen einwandfrei funktioniert, jetzt hingegen habe ich angeblich einen Syntaxfehler wo keiner ist. Ich habe absolut nichts verändert und trotzdem soll auf einmal ein Syntax Fehler da sein...

Außerdem noch eine andere Frage. Ich habe es jetzt geschafft mit dem anderen Programm die Systemzeit des Raspberry automatisch immer auf die aktuell empfangene GPS-Zeit zu setzen. Diese möchte ich nun in das Textfile schreiben, anstatt diese Zeit aus der anderen Textdatei zu holen. Bekomme es allerdings (mal wieder) nicht hin.

Die Zeit in Millisekunden seit dem 01.01.1970 hole ich mir so:

Code: Alles auswählen

import datetime from datetime
dt = datetime.now()
dt.microsecond
print dt
Diese würde ich nun gerne in das interrupt.txt schreiben. Bekomme aber keine Ausgabe, wenn ich das versuche...
BlackJack

@Dexter: Was versuchst Du denn um das in eine Datei zu schreiben? Wobei Du da auch gar nicht die Millisekunden ausgibst sondern das `datetime`-Objekt. Und dann sind Mikrosekunden etwas anderes als Millisekunden und die Mikrosekunden die Du so von `dt` abfragst ist auch wirklich nur der Mikrosekundenanteil an der aktuellen Zeit, also das was übrig bleibt wenn man Stunden, Minuten, und Sekunden abzieht, und nicht etwa die Mikrosekunden seit 1970. Da möchtest Du vielleicht lieber ohne irgendwelche Umwege die Sekunden seit „the Epoch” mit `time.time()` auslesen und mit 1000 multiplizieren.
Dexter
User
Beiträge: 10
Registriert: Freitag 10. Januar 2014, 03:44

Das hatte ich vorher schon so, also:

Code: Alles auswählen

import time
milliseconds = int(round(time.time()*1000))
print milliseconds
Da erhalte ich dann, wie du schon sagtest die Mellisekunden seit epoch. Allerdings muss ich dass dann ja wieder alles umrechnen, um auf ein Datum im gewünschten Format zu kommen. Wohingegen mir datetime direkt das richtige Format gibt. Und du bist dir sicher, dass dabei die Millisekunden einfach weggelassen werden? Das ergibt doch keinen Sinn. Wenn dann sind die Millisekunden einfach in den Mikrosekunden enthalten, was ja völlig egal ist, da die Genauigkeit so nur noch steigt.

ps.: Diese Zeit soll ganz simpel untereinander in eine Textdatei geschrieben werden, sobald ein Event eintritt.
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Einfach mal testen:

Code: Alles auswählen

In [9]: import datetime

In [10]: datetime.datetime.now().microsecond
Out[10]: 836896

In [11]: import time

In [12]: time.time()
Out[12]: 1389784605.812602
Jetzt ist [10] > 1000, das koennen also nicht nur die Mikrosekunden sein sondern auch noch die Millisekunden. Vergleichen wir das aber mit [11] dann wird auch deutlich, dass es auf keinen in Richtung Epoch geht.

Was BlackJack meinte ist nicht, dass es nicht die Mikrosekunden und die Millisekunden sind, sondern dass es _nicht_ die Darstellung der Zeit in Mikrosekunden sind - und schon gar nicht seit Epoch, denn dafuer machen nur Sekunden Sinn.
Soll heissen, mit datetime musst du selbst noch die Sekunden, Minuten, Tage, ...., Jahre zusammenzaehlen und die Differenz zu Epoch bilden, wenn du das richtige Ergebnis haben willst.
Dexter
User
Beiträge: 10
Registriert: Freitag 10. Januar 2014, 03:44

Okay, vielleicht reden wir aneinander vorbei. Ich habe ein Programm, welches die GPS-Zeit von einem GPS 50 mal die Sekunde bekommt. Diese GPS-Zeit wird von dem Programm als Systemzeit gesetzt.
Das Python-Script hier, soll sich nur diese Zeit holen und im gewünschten Format in eine Textdatei speichern, sobald das Event an der GPIO Pins meines Pi's kommt.
Und genau das passiert, wenn ich datetime.now() verwende. Ich bekomme genau die Zeit, die ich auch so in der oberen Linken Ecke meines Desktops sehe, außer das hinten noch milli und mikrosekunden dran sind. Also die Genauigkeit höher ist, als die "normale" Systemzeit.

Oder habe ich jetzt irgendwas immer noch nicht verstanden und sehe das Problem nicht? Für mich ist im Moment das einzige Problem, diese ausgelesene Zeit in eine Textdatei zu schreiben.
BlackJack

@Dexter: Du hast aber erst nach den Millisekunden seit Epoch gefragt. Anscheinend brauchst Du die gar nicht. Wenn Dir die Standard-Zeichenkettendarstellung von `datetime`-Objekten zusagt, dann wandel das Objekt einfach in eine Zeichenkette und schreib die dann in eine Datei. Wenn Du die Formatierung der Zeit selber beeinflussen willst, dann verwende zur Umwandlung die `strftime()`-Methode.
Dexter
User
Beiträge: 10
Registriert: Freitag 10. Januar 2014, 03:44

Das tut mir leid, dann habe ich mich vorher zu undeutlich ausgedrückt. Bei mir funktioniert eben dieses schreiben der Zeit in eine txt nicht. Einfach so schreiben mit fh.write() klappt super. Nur bekomme ich das nicht in die Schleife eingebaut, damit es jedes mal geschrieben wird, sobald ein Event eintritt. Irgendwas mache ich da falsch, ich kann morgen (bei euch mitten in der Nacht) mal den Code posten, mit dem ich das versucht habe. Habe ich gerade keinen Zugriff drauf, da der nur aufm Pi liegt.
Das Readfile kann ich jetzt ja wegnehmen, da ich vorher keine txt mehr zum lesen öffnen muss...
Benutzeravatar
/me
User
Beiträge: 3556
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

Dexter hat geschrieben:Bei mir funktioniert eben dieses schreiben der Zeit in eine txt nicht. Einfach so schreiben mit fh.write() klappt super. Nur bekomme ich das nicht in die Schleife eingebaut, damit es jedes mal geschrieben wird, sobald ein Event eintritt.
Der folgende Code schreibt bei mir problemlos die ganze Datei voll.

Code: Alles auswählen

with open(filename, 'w') as fh:
    while True:
        fh.write('{}\n'.format(datetime.datetime.today()))
        fh.flush()
Das flush ist nur dafür da, um beim manuellen Abbruch der Schleife wirklich alle Daten bereits geschrieben zu haben.
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Alternativ kann man auch das oeffnen der Datei (dann im schon angesprochenen "append" Modus) in die Schleife ziehen.

Code: Alles auswählen

while True
    with open(filename, 'a') as fh:
        fh.write('{}\n'.format(datetime.datetime.today()))
Das wuerde ich aber nur bei einer Schleife bevorzugen, die tatsaechlich mehr tut als nur die einzelne Zeile zu schreiben.
Dexter
User
Beiträge: 10
Registriert: Freitag 10. Januar 2014, 03:44

Vielen Dank an alle, die mir geholfen haben. Funktioniert jetzt alles soweit wie ich mir das vorstelle!

Viele Grüße,
Dexter
Antworten