Seite 1 von 2

Verfasst: Donnerstag 5. April 2007, 18:26
von BlackJack
Zeile für Zeile vergleichen wird wahrscheinlich nicht soviel bringen, weil die Dateien nicht gleich lang sind wenn Dateien hinzukommen.

Die Situation lässt sich am einfachsten mit `set()`\s lösen, Dich interessieren ja Mengenoperationen auf Zeilen.

Verfasst: Freitag 6. April 2007, 10:23
von BoOnOdY
Das set ist schon ma sehr cool :)


also ich hab jetzt mal ein bisschen hier im Forum geforscht und hätt noch ein paar Fragen.

also in dem Beitrag will jemand ja nur die Datei mit dem aktuellen Datum haben.
http://www.python-forum.de/topic-7347.h ... hlight=ftp
und hier hat ja auch jemand ein ähnliches Problem
http://www.python-forum.de/topic-8231.h ... hlight=ftp

Wenn man davon ausgehen kann, dass die Datei die ich rein schreibe einen Zeitstempel als Namen hat, dann könnte ich ja einfach alle möglichen Zeitstempel ausprobieren. Also jede Minute versuchen ein File mit dem aktuellen Zeitstempel herunter zu laden. Aber belastet ist das denn nicht ganz schön Aufwenig von der Leistung her?

Da wäre es doch einfacher die Prozedur in eine IF abfrage zu stecken, die erst einmal nachsieht ob ein entsprechendes File auf dem Server ist, und wenn ja dann soll es sich das File holen.

Also ein einfaches Programm das jede Minute guckt, ob ein File mit dem entsprechenen Timestamp auf dem Server ist. Aber da ich so gut wie keine Erfahrungen in Python habe frage ich mich wie das geht.

Von der Logik her.

Anfang
Aktuelle Uhrzeit in Stunden und Minuten mit einer Variablen vergleichen
if Uhrzeit ist ungleich Variable,
aktuelle Uhrzeit in Variable schreiben
versuche Datei vom FTP server zu laden die den entsprechenden Namen hat
go to Anfang


Weil das mit der Zeit in dem Dateinamen könnte ich einfach hinbekommen, aber ist es nicht sehr aufwendig jede Minute zu gucken?, aber wie will man sonst den Dateinamen der wirklich jede Minute sein könnte herausfinden?

Ich glaube das Programm würde die CPU ziemlich auslasten, und ich trau mich erlich gesagt das nicht zu versuchen weil ich Angst hab, dass ich es nicht mehr aus bekomme wiel ich in ner Endlosschleife lande die die CPU so auslastet das man nix mehr machen kann, udn ich komm auf den PC auf dem ich das probieren will nur mit Remote Desktop ran. Da wäre das ziemlich kompliziert.

Ist denn das Time Objekt wirklich immer variabel?, also das Programm schaut sich es nicht nur an wenn es gerade gestartet wird, sondern so lange, bis es die Bedinung erfüllt?


Ich weiß es sind viele Fragen und wohlmöglich auch manchmal unklar gestellt, aber ich kann sie im Moment leider nicht verständlicher Formulieren, bin aber für Rückfragen immer zur Stelle.

Gruß BoOnOdY

Verfasst: Freitag 6. April 2007, 11:46
von gerold
Hallo BoOnOdY!

Ich habe mir jetzt nicht die Mühe gemacht, die Beiträge komplett durchzulesen.

Ich gebe dir jetzt einen kleinen Gedankenschupser. Und wenn du damit nichts anfangen kannst, weil ich die Randbedingungen nicht kenne, dann ignoriere den Stoß. ;-)

Das Kommandozeilenprogramm "wget" kann Dateien von einem FTP-Server herunterladen. Wenn man "wget" mit dem Parameter "--mirror" benutzt, dann wird auf dem Computer auf dem "wget" ausgeführt wird, ein kompletter **Spiegel** des angeforderten FTP-Ordners angelegt. Wird "wget" mit dem Parameter "--mirror" danach noch einmal ausgeführt, dann werden nur mehr die **geänderten** Dateien vom FTP-Server geholt.

Und jetzt kommt noch so ein Denkanstoß: Wenn man "wget" zusätzlich mit dem Parameter "-o logdatei.log" ausführt, dann wird jede Aktivität von "wget" in die Datei "logdatei.log" geschrieben. Z.B. so: ``wget --mirror ftp://gelb.bcom.at -o logdatei.log``

Rate mal was ebenfalls in dieser Logdatei steht. --> Die Dateien die neu heruntergeladen wurden. Neben diesen steht nämlich der String "saved".
Z.B. so (schon mal nach "saved" gefiltert):

Code: Alles auswählen

12:14:36 (212.18 KB/s) - `gelb.bcom.at/.listing' saved [188]
12:14:36 (282.51 KB/s) - `gelb.bcom.at/index.html' saved [623]
12:14:37 (477.68 KB/s) - `gelb.bcom.at/sw3/.listing' saved [67]
12:14:37 (409.21 KB/s) - `gelb.bcom.at/test/.listing' saved [67]
12:14:37 (275.20 KB/s) - `gelb.bcom.at/test/index.html' saved [623]
Wenn du jetzt alle Zeilen herausfilterst, in denen "saved [" steht und die Zeilen mit dem Text ".listing" ignorierst, dann hast du eine Liste aller Dateien, die sich auf dem FTP-Server geändert haben.

Es geht sogar noch einfacher: Wenn du zusätzlich den Parameter "--no-verbose" verwendest. Sieh selber nach, wie die Logdatei damit aussieht. :-)

Jetzt musst du nur noch die neuen/geänderten Dateien in ein komprimiertes TAR-Archiv oder sonst wo in ein Archiv kopieren und dem Archiv als Dateinamen das aktuelle Datum und die Uhrzeit geben.

Jetzt hast du immer einen aktuellen Spiegel des FTP-Servers und die Änderungen sind gesammelt in TAR-Dateien

mfg
Gerold
:-)

Verfasst: Freitag 6. April 2007, 11:52
von gerold
Und so könnte man dieses Logfile parsen:

Code: Alles auswählen

>>> s = """
... 12:44:44 URL: ftp://gelb.bcom.at/ [188] -> "gelb.bcom.at/.listing" [1]
... 12:44:44 URL: ftp://gelb.bcom.at/index.html [614] -> "gelb.bcom.at/index.html" [1]
... 12:44:44 URL: ftp://gelb.bcom.at/sw3/ [67] -> "gelb.bcom.at/sw3/.listing" [1]
... 12:44:45 URL: ftp://gelb.bcom.at/test/ [67] -> "gelb.bcom.at/test/.listing" [1]
... 12:44:45 URL: ftp://gelb.bcom.at/test/index.html [614] -> "gelb.bcom.at/test/index.html" [1]
... 
... FINISHED --12:44:45--
... Downloaded: 1,550 bytes in 5 files
... """
>>> for line in s.splitlines():
...     if '"' in line:
...         parsed_str = line.split('"')[1]
...         if not parsed_str.endswith(".listing"):
...             print parsed_str
...     
gelb.bcom.at/index.html
gelb.bcom.at/test/index.html
>>> 
mfg
Gerold
:-)

Verfasst: Freitag 6. April 2007, 12:11
von BoOnOdY
Vielen Dank :)

Ich werde mal ein bisschen was zu wget lesen und ausprobieren.

Aber hier trozdem der Background einfach und kurz erklärt:

Ich habe ein kleines Adressbuch aller meiner Freunde im Keller auf einem SQL Server.

Jeder kann auf einem FTP Server seine Adressdatei hoch laden. Die hat ein festes Format das jeder kennt.
Hans läd seine Datei heute um 12:11 Uhr auf den FTP Server

Dann soll das Programm eingreifen, das erkennen und den Namen der Datei in ein Log schreiben. Danach soll es die Datei in einen bestimmten Ordner auf dem Server auf dem der Skript läuft schreiben.Dann soll es ein Programm ( das ich schon fertig habe) anstoßen, das diese Adressdatei filtert, sortiert und in die Datenbank schreibt. Dieses Filter-programm holt sich den Namen der zu filternden Datei aus der log.

Was passiert aber wenn um 12:12 dazu noch Christian seine Datei hochläd und ich nur alle 5 Minuten nach neuen Files gucke?

Verfasst: Freitag 6. April 2007, 13:05
von gerold
BoOnOdY hat geschrieben:Jeder kann auf einem FTP Server seine Adressdatei hoch laden. Die hat ein festes Format das jeder kennt.
Hi BoOnOdY!

Zwischenfrage: Wie heißen diese Dateien? Haben die eine besondere Dateiendung oder sind alle Dateien in einem bestimmten Ordner und in diesem Ordner darf keine andere Datei sein?

mfg
Gerold
:-)

Verfasst: Freitag 6. April 2007, 13:27
von BoOnOdY
Hy,

die sind alle in einem Ordner und haben einen bestimmten Namen und eine bestimmte Endung, da sind noch Zip-Dateien und so drinne, aber die könnte ich rausnehmen, wär aber um so besser wen ndas Programm die nicht berücksichtigen würde :) :

wenn sie am 6 April 2007 um 14:26 Uhr hochgeladen wurde, dann heißt sie:

060420071426.adb


Aber es darf natürlich keine doppelt importiert werden, sondern immer nur die Neuste.

Gruß BoOnOdY

Verfasst: Freitag 6. April 2007, 14:01
von gerold
Hi!

Probiers mal so:

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-

import os
import ftplib
import pickle

DIRSET_FILENAME = "dirset.bin"
FTP_HOST = "gelb.bcom.at"
FTP_USERNAME = "anonymous"
FTP_PASSWORD = ""
LOGFILENAME = "logfile.log"


def load_dirset():
    """
    Holt sich aus einer gepickelten Datei ein Set mit den Textzeilen des
    letzten Versuchs.
    """
    
    if os.path.isfile(DIRSET_FILENAME):
        f = file(DIRSET_FILENAME, "rb")
        dirset = pickle.load(f)
        f.close()
    else:
        dirset = set()
    
    return dirset


def save_dirset(dirset):
    """
    Schreibt das übergebene Set in eine Datei
    """
    
    f = file(DIRSET_FILENAME, "wb")
    pickle.dump(dirset, f, protocol = pickle.HIGHEST_PROTOCOL)
    f.close()


def main():
    
    ftp = ftplib.FTP(FTP_HOST, FTP_USERNAME, FTP_PASSWORD)
    
    old_dirset = load_dirset()
    new_dirset = set()
    
    dirlist = []
    ftp.dir(dirlist.append)
    
    for diritem in dirlist:
        if not diritem.startswith("d"):
            if diritem.lower().endswith(".adb"):
                new_dirset.add(diritem)
    
    # Hier sind die geänderten Datenzeilen
    diff_dirset = new_dirset.difference(old_dirset)
    
    print old_dirset
    print
    print new_dirset
    print
    print diff_dirset
    print
    
    # Die Dateinamen können hier natürlich auch in eine Logdatei geschrieben
    # werden
    f = file(LOGFILENAME, "a")
    for item in diff_dirset:
        f.write(item + "\n")
    f.close()
    
    # Hier kann mit den geänderten Datenzeilen etwas gemacht werden.
    # Z.B. kann jetzt eine Liste mit Dateinamen erstellt werden
    waste = "-rw-r--r--   1 ftp      ftp             0 Apr  6 12:39 "
    filenames = [ item[len(waste):] for item in diff_dirset ]
    
    print filenames
    
    # Dateien herunterladen
    for filename in filenames:
        f = file(filename, "wb")
        ftp.retrbinary("RETR %s" % filename, f.write)
        f.close()
    
    # Neues Set speichern
    save_dirset(new_dirset)
    
    ftp.close()

if __name__ == "__main__":
    main() 

# Nicht vergessen: Fehler abfangen
mfg
Gerold
:-)

Verfasst: Freitag 6. April 2007, 18:03
von BoOnOdY
Vielen Dank :)
Also ich les mich da im Moment rein udn probier einiges aus
ich hätte noch 2 winzige Fragen:



Code: Alles auswählen

 b = file("E:\AEP\UglyProg\log.log", "wb")
    for filename in filenames: 
        b.write(filename + "\n")
    b.close()
ich hab das noch eingefügt.
aber irgendwie funktioniert nach der Zeile
# Hier kann mit den geänderten Datenzeilen etwas gemacht werden.
# Z.B. kann jetzt eine Liste mit Dateinamen erstellt werden
waste = "-rw-r--r-- 1 ftp ftp 0 Apr 6 12:39 "
filenames = [ item[len(waste):] for item in diff_dirset ]
nichts mehr weiter?



Frage nummer 2.

Wie bau ich da eine Schleife drum herumm, die immer wenn die Minuten des Aktuellen timestamps 0, 5, 10 15, 20,25,30,35,40,45,50,55 sind das ganze ausführt??
Wenn ich das mit ner einfachen If-Abfrage mache brauch das dan nicht sehr viel CPU Leistung?

Gruß, vielen Dank und Frohe Ostern

BoOnOdY

Verfasst: Freitag 6. April 2007, 18:53
von gerold
Hi BoOnOdY!
BoOnOdY hat geschrieben:

Code: Alles auswählen

 b = file("E:\AEP\UglyProg\log.log", "wb")
    for filename in filenames: 
        b.write(filename + "\n")
    b.close()
Einrückungsfehler?; Backslashes (\) nicht doppelt im String; Warum verwendest du keine Konstante um den Dateinamen im Programmkopf festzulegen?
BoOnOdY hat geschrieben:Wie bau ich da eine Schleife drum herumm, die immer wenn die Minuten des Aktuellen timestamps 0, 5, 10 15, 20,25,30,35,40,45,50,55 sind das ganze ausführt?
So was macht man nicht im Programm. Dafür ist unter Linux der "cron"-Daemon (=Dienst) zuständig und unter Windows richtet man für so etwas einen "Geplanten Task" (über die Systemsteuerung) ein.

mfg
Gerold
:-)

Verfasst: Freitag 6. April 2007, 19:37
von BoOnOdY
Hy,

sorry das ich mich so verdammt dumm anstele, aber wenn ich den Skript kopiere so wie er hier im Forum steht und noch eine kleine Änderung mache (ein change direktory im FTP) schreibt er mir nichts in meine log und nur so eine komische Zeichenfolge in die Dirset.bin
€c__builtin__
set
q ]q…qRq.

Code: Alles auswählen

#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-

import os
import ftplib
import pickle

DIRSET_FILENAME = "dirset.bin"
FTP_HOST = "1****"
FTP_USERNAME = "admin"
FTP_PASSWORD = "****"
LOGFILENAME = "logfile.log"
MONOLOG = "E:\\AEP\\Uglyprog\\log.log"



def load_dirset():
    """
    Holt sich aus einer gepickelten Datei ein Set mit den Textzeilen des
    letzten Versuchs.
    """
   
    if os.path.isfile(DIRSET_FILENAME):
        f = file(DIRSET_FILENAME, "rb")
        dirset = pickle.load(f)
        f.close()
    else:
        dirset = set()
   
    return dirset


def save_dirset(dirset):
    """
    Schreibt das übergebene Set in eine Datei
    """
   
    f = file(DIRSET_FILENAME, "wb")
    pickle.dump(dirset, f, protocol = pickle.HIGHEST_PROTOCOL)
    f.close()


def main():
   
    ftp = ftplib.FTP(FTP_HOST, FTP_USERNAME, FTP_PASSWORD)
   
    old_dirset = load_dirset()
    new_dirset = set()
   
    dirlist = []
    ftp.cwd("\\CDR\\checkout")
    ftp.dir(dirlist.append)
   
    for diritem in dirlist:
        if not diritem.startswith("d"):
            if diritem.lower().endswith(".adb"):
                new_dirset.add(diritem)
   
    # Hier sind die geänderten Datenzeilen
    diff_dirset = new_dirset.difference(old_dirset)
   
 

    print old_dirset
    print
    print new_dirset
    print
    print diff_dirset
    print 
   
    # Die Dateinamen können hier natürlich auch in eine Logdatei geschrieben
    # werden
    f = file(LOGFILENAME, "wb")
    for item in diff_dirset:
    	f.write(item + "\n")
    f.close()
   
    # Hier kann mit den geänderten Datenzeilen etwas gemacht werden.
    # Z.B. kann jetzt eine Liste mit Dateinamen erstellt werden
    waste = "-rw-r--r--   1 ftp      ftp             0 Apr  6 12:39 "
    filenames = [ item[len(waste):] for item in diff_dirset ]
   
    print filenames
   
    b = file(MONOLOG, "wb")
    for filename in filenames: 
    	b.write(filename + "\n")
    b.close()

    # Dateien herunterladen
    for filename in filenames:
    	f = file(filename, "wb")
    	ftp.retrbinary("RETR %s" % filename, f.write)
    	f.close()
   
    # Neues Set speichern
    save_dirset(new_dirset)
   
    ftp.close()

if __name__ == "__main__":
    main()
[/quote]

Verfasst: Freitag 6. April 2007, 19:53
von gerold
BoOnOdY hat geschrieben:

Code: Alles auswählen

ftp.cwd("\\CDR\\checkout")
Hi BoOnOdY!

Die komischen Zeichen in der Bin-Datei sind schon OK. Das ist ja auch keine menschenlesbare Datei.

Mach mal das daraus, dann dürfte es funktionieren:

Code: Alles auswählen

ftp.cwd("/CDR/checkout")
Du musst deinen Code natürlich zuerst einmal in einer Konsole oder in einer IDE laufen lassen, damit du die Fehlermeldungen zurück bekommst. Sonst ist das ja ein Blindflug.

mfg
Gerold
:-)

Verfasst: Freitag 6. April 2007, 20:08
von BoOnOdY
Hey =)
vielen Dank es geht alles super.
Sau geil, auf euch kann man sich immer verlassen.
=)=)=)=)

Gruß BoOnOdY