Hallo
Ich bekomme einen Error, wenn zwei laufende Skripte gleichzeitig auf eine pickle Datei zugreifen wollen.
Kann ich das irgendwie verhindern dass die gleichzeitig darauf zugreifen?
Hallo
Ich bekomme einen Error, wenn zwei laufende Skripte gleichzeitig auf eine pickle Datei zugreifen wollen.
Kann ich das irgendwie verhindern dass die gleichzeitig darauf zugreifen?
Gleichzeitiger Zugriff auf Datei verhindern? Schau mal ob du hier fündig wirst!
Zeig die Scripte.
Also das erste Skript ist:
[code=php]
def read():
with open('/home/pi/time.pkl') as f:
t = pickle.load(f)
print(t)
return t
def write():
with open('/home/pi/time.pkl','wb') as f:
value = time.time()
pickle.dump(value,f)
while True:
if time.time() - read() >= max:
print "LED ein!"
GPIO.output(24,GPIO.HIGH)
time.sleep(1)
GPIO.output(24,GPIO.LOW)
write()
time.sleep(1)[/php]
Das zweite Skript wird von einem Sensor aufgerufen und kommt deshalb unregelmässig:
[code=php]
import time
import pickle
def write():
with open('/home/pi/time.pkl','w') as f:
value = time.time()
print value
pickle.dump(value,f)
write()[/php]
Ich bekomme dann den Error:
[code=php]Traceback (most recent call last):
File "read_time.py", line 53, in <module>
if time.time() - read() >= max:
File "read_time.py", line 28, in read
t = pickle.load(f)
File "/usr/lib/python2.7/pickle.py", line 1378, in load
return Unpickler(file).load()
File "/usr/lib/python2.7/pickle.py", line 858, in load
dispatch[key](self)
File "/usr/lib/python2.7/pickle.py", line 880, in load_eof
raise EOFError
EOFError[/php]
Ich glaube dass der kommt weil beide Skripte gleichzeitig auf die time.pkl Datei zugreifen wollen ... :s
Danke für Tipps
Wenn ich das richtig verstehe dann verwendest du die Datei einfach nur um den aktuellen Timestamp rein zu schreiben, oder? :s Warum du das machst versteh ich allerdings noch nicht...
Anstatt diesen Wert zu verwenden würde ich die 'modification time' der Datei abrufen.
Also:
Dein Sensor-Script schreibt einfach 'irgend etwas' in die Datei. Dein 2.Script prüft dann regelmässig besagte "last modification time" der Datei und muss somit nicht mehr direkt die Datei öffnen und auslesen:
[code=php]import os.path, time
while True:
if os.path.isfile('/home/pi/time.pkl'):
lastTime = os.path.getmtime('/home/pi/time.pkl')
if time.time() - lastTime >= max:
print "LED ein!"
GPIO.output(24,GPIO.HIGH)
time.sleep(1)
GPIO.output(24,GPIO.LOW)
time.sleep(1)
[/php]
Allerdings würde diese while dann ständig anschlagen und die LED jede Sekunde erneut eingeschaltet werde da die Prüfung ">= max" kein Ende findet.
Besser wäre:
[code=php]import os.path, time
lastTime=None
while True:
if os.path.isfile('/home/pi/time.pkl'):
if lastTime and (os.path.getmtime('/home/pi/time.pkl') <> lastTime):
print "LED ein!"
GPIO.output(24,GPIO.HIGH)
time.sleep(1)
GPIO.output(24,GPIO.LOW)
lastTime = os.path.getmtime('/home/pi/time.pkl')
time.sleep(1)
[/php]
Dann schlägt er wirklich nur dann ein mal an wenn die Datei verändert wurde.
Danke für die Hilfe meigrafd und bootsmann!
bootsmann: hab jetzt überall die rb und wb ergänzt. Aber der Error kommt leider immer noch
meigrafd: Genau, er schreibt nur die Zeit da rein. Das Deshalb, weil ich die Zeit vom Sensor irgendwie in das erste Skript bringen muss für den Vergleich >= max. Mir ist da keine Andere Variante bekannt gewesen als dieses pickle.
Ich verstehe noch nicht ganz was das Zeichen '<>' macht?
Und wieso hast du das /tmp/time.pkl verwendet bei der zweiten Variante und nicht das /home/pi/time.pkl?
Ich verstehe noch nicht ganz was das Zeichen '<>' macht?
Guckst du: http://www.tutorialspoint.com/python/python_basic_operators.htm
Und wieso hast du das /tmp/time.pkl verwendet bei der zweiten Variante und nicht das /home/pi/time.pkl?
Ignorier das. Spielt keine Rolle welche Datei wo liegt.... Hauptsache immer die selbe. War von mir ein 'copy&paste' Fehler..
Ich nutze generell /tmp/ da das bei mir tmpfs is (sowas wie eine ramdisk) und somit nicht die SD mit unnötigen Schreibvorgängen belastet - dieser Pfad stammt also von meinem Test vorhin, um nicht irgendwelche Vermutungen zu posten sondern tatsächlich funktionierendes...
bootsmann: hab jetzt überall die rb und wb ergänzt. Aber der Error kommt leider immer noch
Dann hast du anscheinend es irgendwo noch vergessen, denn so gibt es keinen Fehler:
Programm 1:
import pickle
import time
def read():
with open('time.pkl', 'rb') as f:
t = pickle.load(f)
print(t)
return t
def write():
with open('time.pkl','wb') as f:
value = time.time()
pickle.dump(value,f)
while True:
if time.time() - read() >= max:
print "LED ein!"
time.sleep(1)
write()
time.sleep(5)
Alles anzeigen
Programm 2:
bootsmann: Ja bei mir hat es zuerst auch keinen Error gegeben, erst nach einiger Zeit, als wahrscheinlich beide Skripte gleichzeitig aufgerufen wurden.
In deinem Fall mit den beiden while True und sleep(5) ist es doch eher unwahrscheinlich dass beide Skripte gleichzeitig auf die Datei zugreifen, oder sehe ich das falsch?
meigrafd: Danke, ja das funktioniert. Aber nicht so wie es soll. Denn die LED soll erst Blinken, wenn maxDiff überschritten wurde. Jetzt blinkt sie, sobald der Sensor betätigt wird.
Ich kann jetzt die lastTime nicht mehr auf die aktuelle Zeit setzten.. Aber ich glaube das alles hast du auch schon gesehen.
Ich müsste also doch irgendwie in die Datei reinschreiben können.
Hmm, gäbe es nicht irgend eine andere Variante, mit der der gemeinsame Zugriff Verhindert werden könnte?
Ich habe auch noch .txt Dateien bei denen ein gemeinsamer zugriff von verschiedenen Skripten aus verhindert werden muss. Aber irgendwie finde ich das keine Idee wie ich das machen kann.. :s
Oder gibt es ein mutex oder so dass ich verwenden könnte?
Ich müsste also doch irgendwie in die Datei reinschreiben können.
Wozu?
Ich glaub du hast nicht verstanden was da überhaupt passiert...
Ob du nun den letzten Aufruf des Sensors als unixtimestamp in eine Datei rein schreibst, oder anhand der "last modification time" heraus findest - spielt kaum eine Rolle, nur eben Dein Problem dass 2 Scripts gleichzeitig auf die Datei zugreifen...
Bevor ich mir jetzt aber die Mühe mache und Dein Problem löse - wäre interessant die Hintergründe bzw das Wieso zu erfahren... Wieso darf nur ein Script schreiben, was macht dieses Script überhaupt, was macht das 2.Script und wieso schreibst du in irgend welchen txt dateien rum?
Wie steckst du nicht beide Code-Blöcke in ein Skript und arbeitest mit dem threading-Modul? Dann könntest du einfach mit threading.Lock() den gleichzeitigen Zugriff verhindern ... da gibt es sehr viele Möglichkeiten.
@ meigrafd: Ja du hast recht, das mit der last modification time funktioniert so wie gesagt hast.
Also ich habe einen Sensor, der ruft bei einer Aktivität das Skript auf welches die Zeit in den Speicher (time.pkl Datei) legt.
Wenn zu lange keine Aktivität von diesem Sensor vorhanden war, soll das bemerkt werden.
Dazu möchte ich die Zeit aus der time.pkl Datei lesen mit dem zweiten Skript und diese Zeit mit der aktuellen Zeit vergleichen.
Deshalb diese Zeile:
[code=php]if time.time() - lastTime >= max:[/php]
Aber ich habe das zuerst falsch geschrieben, es muss nicht nur ein Skript in den Speicher schreiben können, sondern beide. Denn wenn das max überschritten wurde, wird wieder die aktuelle Zeit in den Speicher gelegt. Aber nur das zweite Skript mit der Auswertung muss die Zeit auslesen.
Also beide Skripte schreiben, nur eines liest.
Ich hoffe das ist einigermassen verständlich
Aber ich weiss nicht recht ob das evtl nicht die richtige lösung ist mit der pickle Datei. Evtl gäbe es da bessere Möglichkeiten?
Ich habe noch etwas gefunden, dass evtl das Problem mit dem gemeinsamen Zugriff lösen könnte. Ich würde das write() atomar machen, dass es sicherlich nicht unterbrochen wird:
[code=php]from atomicwrites import atomic_write
def write():
with atomic_write('/home/pi/time.pkl', overwrite=True) as f:
f.write(time.time())[/php]
Könnte das die Lösung sein?
mobby: Danke für den Tipp. Ich kenne mich mit Threads leider sehr wenig aus, und ich glaube das würde mir mehr Probleme bereiten als die andere Variante.. :s
Ich versteh immer noch nicht wieso das auf diesen Weg versuchst und glaube das es anders besser wäre, aber da ich nicht weiß um welchen Sensor es sich handelt kann ich hier nur raten... Ich glaub du gehst das von der falschen Seite an..
Um was für einen Sensor handelt es sich?
Wie ist dieser Sensor angeschlossen?
@ meigrafd: Ich habe jetzt die Variante von dir verwendet mit der "last modification time". Klappt super
Der Error ist nicht mehr aufgetreten.
Ich verwende einen Fensterkontakt von EnOcean
https://www.enocean.com/en/enocean_modules/stm-250-oem/
Der wird über einen USB-Funkempfänger eingelesen.
Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!