Seite 1 von 1
Timer und loop
Verfasst: Mittwoch 27. Februar 2008, 17:21
von nordlocke
Hallo in die Runde,
ich hätte da mal ein Problem
Ich öffne in meinem Programm immer eine Datei (textX.txt), bearbeite diese und dann kommt die nächste.
Das ganze hängt in einer Endlosschleife, da dies immer laufen soll.
Nun würde ich gerne z.B. if Anweisung einbauen oder try/exception.
Falls die Datei zum lesen noch nicht da ist.
Nur das mit dem 'warte 5 min. und dann noch mal probieren'
bereitet mir Problemchen. Ich habe mir schon bisschen zur timer Funktion durchgelesen, aber so richtig habe ich das noch nicht hin bekommen.
Vielleicht hätte hier noch jemand nen Tip für mich.
Danke und Grüße,
Locke.
Code: Alles auswählen
# init Count
count = 0
# Loop forever
while True:
count = count + 1
try:
# open file
path = 'C:\\text%s.txt'%count
file = open (path, r)
print '*** Begin reading file text%s.txt File ***' % count
for line in file:
# hier lese ich die Datei aus
except IOError:
# warte 5 min und dann noch mal probieren
Re: Timer und loop
Verfasst: Mittwoch 27. Februar 2008, 17:37
von audax
Code: Alles auswählen
from time import sleep
FILE_TEMPLATE = 'C:\\text%s.txt'
def main():
count = 0
def open_and_do():
count = count + 1
try:
# open file
path = FILE_TEMPLATE % count
file = open (path, 'r')
print '*** Begin reading file text%s.txt File ***' % count
for line in file:
do_stuff(line)
except IOError:
sleep(300)
return open_and_do()
while True:
open_and_do()
Wobei ich das durchaus unsauber finde so.
Aber gut, wirst schon deine Gründe haben...
Verfasst: Donnerstag 28. Februar 2008, 08:04
von nordlocke
Stimmt mit einer Funktion geht das ja einfach zu lösen, danke für die Hilfe.
Wieso findest du das ganze unsauber, bzw. was?
Verfasst: Donnerstag 28. Februar 2008, 08:33
von audax
Einfach über Dateien iterieren, die über nen Formatstring erstellt werden.....bäh.
Besorg dir lieber irgendwie die Liste dieser Dateien und iteriere darüber, das ist nicht so fehleranfällig.
Btw:
Lagere IMMER ALLE(!) Kontanten aus, wirklich immer!
Das spart einem so unglaublich viel Arbeit, wenn man später noch was ändert...
Eine einfache Variable zu ändern geht fix, mit einer RegExp-Ersetzung durch den ganzen Projektordner zu rattern ist da schon aufwändiger

Verfasst: Donnerstag 28. Februar 2008, 09:00
von nordlocke
Ja das mit den Konstanten, da verfalle ich so manchmal in die Schlamperei, wenn ich das so hin tippe.
Wenn alles läuft schaue ich mir immer noch mal alles an und versuche zu optimieren. Das optimieren nimmt auch meistens mehr Zeit in Anspruch
Das mit der Liste der Dateien ist schwer, da die Textdateien ja nicht statisch dort sind. Die Textdateien in dem Ordner werden halt immer mehr, daher würde eine Liste meines Erachtens keinen Sinn machen oder?
Verfasst: Donnerstag 28. Februar 2008, 09:09
von audax
Kontansten gehören an den Anfang oder ausgelagert, das Refactoring macht wirklich keinen Spaß, glaub mir...
Und wenn schon keine Liste, dann wenigstens ein ausgelagerter Generator:
Code: Alles auswählen
def file_gen(count=0)
def gen():
try:
path = FILE_TEMPLATE % count
return open (path, 'r')
except IOError:
sleep(300)
return gen()
while True:
count += 1
yield gen()
Verfasst: Donnerstag 28. Februar 2008, 09:14
von BlackJack
@audax: Unnötige Rekursion. Wenn das lange läuft und diese Ausnahme wirklich vorkommen, kann man sich damit das Programm wegen dem Rekursionslimit abschiessen.
@nordlocke: Wenn, dann würde ich es so schreiben:
Code: Alles auswählen
from itertools import count
from time import sleep
def main():
for number in count(1):
try:
path = r'C:\text%s.txt' % number
lines = open(path)
except IOError:
sleep(300)
else:
print '*** Begin reading file %s ***' % path
for line in lines:
pass
lines.close()
Allerdings finde ich es komisch, dass nach der Wartezeit mit der nächsten Nummer weiter gemacht werden soll. Ist das Absicht? Und falls es sich hier um das warten auf Dateien handelt, die ein anderer Prozess erstellt, dann gibt's unter Umständen die Gefahr, dass die Datei zwar schon existiert, aber der andere Prozess noch beim schreiben ist, Du ihn in der Leseschleife "überholst" und damit eine nicht vollständige Datei verarbeitest ohne es zu merken.
Edit: Startargument von `count()` angepasst.
Verfasst: Donnerstag 28. Februar 2008, 09:34
von audax
Er soll aber eben nicht mit der nächsten Nummer fortfahren, sondern die gleiche noch einmal versuchen.
Code: Alles auswählen
import sys
def tail_recursion_with_stack_inspection(g):
'''
Version of tail_recursion decorator using stack-frame inspection.
'''
loc_vars ={"in_loop":False,"cnt":0}
def result(*args, **kwd):
if not loc_vars["in_loop"]:
loc_vars["in_loop"] = True
while 1:
tc = g(*args,**kwd)
try:
qual, args, kwd = tc
if qual == 'continue':
continue
except TypeError:
loc_vars["in_loop"] = False
return tc
else:
f = sys._getframe()
if f.f_back and f.f_back.f_back and \
f.f_back.f_back.f_code == f.f_code:
return ('continue',args, kwd)
return g(*args,**kwd)
return result
def file_gen(count=0)
@tail_recursion_with_stack_inspection
def gen():
try:
path = FILE_TEMPLATE % count
return open (path, 'r')
except IOError:
sleep(300)
return gen()
while True:
count += 1
yield gen()
Oder aber:
Code: Alles auswählen
def file_gen()
def gen():
while True
try:
path = FILE_TEMPLATE % count
return open (path, 'r')
except IOError:
sleep(300)
continue
while True:
count += 1
yield gen()
Verfasst: Donnerstag 28. Februar 2008, 10:15
von BlackJack
Das mit der Nummer ist in der ersten Beschreibung nicht so klar gewesen und in der ersten Lösung auch anders.
Naja, noch'n Versuch, weil das `retry_open()` ja wiederverwendbar ist:
Code: Alles auswählen
from itertools import count
from time import sleep
FILENAME_TEMPLATE = r'C:\text%s.txt'
retry_open(filename, mode, wait_time=300, max_retry=None):
for retry in count(1):
try:
return open(filename, mode)
except IOError:
if max_retry and retry >= max_retry:
raise
else:
sleep(wait_time)
def main():
for lines in (retry_open(FILENAME_TEMPLATE % n) for n in count(1)):
print '*** Begin reading file %s ***' % lines.name
for line in lines:
pass
lines.close()
Verfasst: Donnerstag 28. Februar 2008, 11:29
von nordlocke
Das mit der retry_open() funktion sieht gut aus.
Ich habe damit mal herum probiert, aber ich bekomme immer Syntaxfehler.
retry_open(filename, mode, wait_time=300, max_retry='None'):
SyntaxError: invalid syntax
Kannst du mir sagen wo ich dazu Infos finde? Zu dem retry_open
Verfasst: Donnerstag 28. Februar 2008, 13:10
von Leonidas
nordlocke hat geschrieben:Das mit der retry_open() funktion sieht gut aus.
Ich habe damit mal herum probiert, aber ich bekomme immer Syntaxfehler.
Da gehört ja auch noch ein ``def`` davor, weil es eben ``retry_open`` implementiert.
Verfasst: Donnerstag 28. Februar 2008, 13:19
von nordlocke
Danke, ich sollte mir noch mal Funktionen unter Python durchlesen.
Verfasst: Donnerstag 28. Februar 2008, 14:53
von BlackJack
Ups
@nordlocke: Ich habe den Typ `None` für `max_retry` verwendet und keine Zeichenkette mit dem Inhalt 'None'. Das sind zwei unterschiedliche Dinge.
Verfasst: Donnerstag 28. Februar 2008, 16:23
von nordlocke
Das ist mir schon aufgefallen, dachte du hättest einfach die '' vergessen und das ignoriert.
Wozu machst du genau die for schleife mit den retrys?
um eine Endlosschleife nicht zu bekommen?
Gibt es eigentlich die Möglichkeit zu sehen ob die Textdatei noch benutzt wird?
Ein anderes Programm legt ja die Dateien an und schreibt sie voll.
Momentan ist ja der stand das ich schaue ist die Datei schon da oder nicht.
Es kann ja aber auch sein, das die Datei schon da ist, aber noch ab voll schreiben ist. Kann man das auch abfangen?
Verfasst: Donnerstag 28. Februar 2008, 17:04
von BlackJack
@nordlocke: Das `max_retry` kann man auf die maximale Zahl der Wiederholungen setzen, bevor der `IOError` an den Aufrufer der Funktion weiter gegeben wird. Wenn `max_retry` ein "falscher" Wert ist, also zum Beispiel `None`, dann wird endlos wiederholt. Nicht ganz, weil `itertools.count()` "nur" `sys.maxint` Zahlen liefert, aber das sind bei 5 Minuten warten zwischen den Versuchen selbst auf einem 32-Bit-System etwas mehr als 20000 Jahre. Was man schon irgendwie als "endlos" bezeichnen kann.
Einen zuverlässigen, portablen Weg um zu erkennen, ob die Datei noch nicht fertig geschrieben wurde, kenne ich nicht. Wenn Du das schreibende Programm beeinflussen kannst, solltest Du erst in eine temporäre Datei schreiben, und diese wenn sie fertig ist umbenennen. Damit erscheinen die Daten für jemanden, der auf diese Datei wartet "auf einen Schlag".
Verfasst: Donnerstag 28. Februar 2008, 18:47
von audax
BlackJack hat geschrieben:@nordlocke: Das `max_retry` kann man auf die maximale Zahl der Wiederholungen setzen, bevor der `IOError` an den Aufrufer der Funktion weiter gegeben wird. Wenn `max_retry` ein "falscher" Wert ist, also zum Beispiel `None`, dann wird endlos wiederholt. Nicht ganz, weil `itertools.count()` "nur" `sys.maxint` Zahlen liefert, aber das sind bei 5 Minuten warten zwischen den Versuchen selbst auf einem 32-Bit-System etwas mehr als 20000 Jahre. Was man schon irgendwie als "endlos" bezeichnen kann.

Ach. Aber bei einer Endlosrekursion meckern...das sind auch einige tausend Tage.
Verfasst: Donnerstag 28. Februar 2008, 19:25
von BlackJack
Das kommt darauf an wie oft so ein IOError vorkommt. Wenn der `IOError` permanent kommt sind das bloss ca. 3½ Tage.
Man sollte sich diese rekursiven "Schleifen" besser gar nicht erst angewöhnen, wenn bei 1000 Aufrufen schon Schluss ist. Diese Grenze trifft man dann unter Umständen recht schnell.
Verfasst: Freitag 29. Februar 2008, 09:32
von nordlocke
Das ist ne menge Zeit
Ich habe auch nichts spezielles zur Datei gefunden, weiß auch gar nicht ob Windows das erkennt, leider läuft das Programm nämlich auf einer Windowskiste, daher habe lasse ich nun in eine Temporäredatei schreiben und wenn das fertig ist speichere ich es erst richtig weg.
Danke für die ganzen Tips und ein schönes Wochenende.