Durchsuchen und öffnen jeder Datei in einem riesiegen Verzeichnis.

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
GotchaInSight
User
Beiträge: 2
Registriert: Freitag 10. Januar 2020, 11:56

Guten Morgen Python Forum.

Ich möchte euch erst einmal ein wenig zu meiner Person und meinem Problem erzählen, weil es höchst wahrscheinlich sowieso zu diesen Fragen kommen wird.
Ich bin neuer Informatikstudent. Ich bin nicht hier um meine Hausaufgaben von euch lösen zu lassen, wie es hier mehrmals angesprochen wurde.^^ Mein Problem hat nichtmal direkt etwas mit meinem Studium zu tun.
Beim Eintritt in mein Informatikstudium, dass ich zur Überbrückung benutze bis meine Ausbildung zum Fachinformatiker Systemintegration im kommenden Jahr beginnt, habe ich mir gedacht es wäre ine gute Idee schonmal praktische Erfahrung im Bereich IT zu sammeln und habe mich bei einem Unternehmen als IT Trainee anstellen lassen.

Meine Aufgabe in diesem Unternehmen ist es neben einem guten Einblick in die IT zu bekommen, mich um ein Verzeichnis zu kümmern, welches im Zuge eines Serverabsturzes Datenverluste erlitten hat.
"Kann man doch einfach das Backup nutzen und neu aufspielen" sagen mir alle Leute in dien Foren. Dem stimme ich auch vollkommen zu, aber leider ist die Situation in diesem Unternehmen eine etwas kompliziertere.
Das Unternehmen ist eine Tochter des Mutterkonzerns in Asien, der Jahrelang ignoriert hat, wie veraltet die Server, Festplatten ... eigentlich alles an der Hardware geworden ist. Das Risiko eines Datenverlustes wurde immer größer bis es zu dem Knall kam. Es gab keine Backups mehr. Keine Server oder irgendwas. Die Kosten der Datenwiederherstellung von 50k wurden abgewiesen. Es wurde mit den Daten weitergearbeitet die übrig waren.
Und über Zeit einfach aussortiert welche Daten beschädigt waren und welche nicht.

Konkret habe ich ein Verzeichnis welches auf Fehler überprüft werden muss. Jede Datei muss geöffnet, geschlossen und markiert werden ob sie funktioniert oder nicht. Das ist alles. Hierfür wurde mir eine Excel Tabelle mit einem Link zu jeder Datei gegeben, dem dazugehörigen Pfad und einem Feld in dass ich reinschreibe ob die Datei intakt ist oder nicht. Intakt sei hierbei wie folgt definiert: Lässt sich die Datei mit dem Standardprogramm öffnen oder nicht. Die Kollegen, welche mit den Dateien arbeiten müssen, unterscheiden nicht ob ich auf die Datei zugreifen kann, ob mein Programm sie überhaupt findet etc. für sie ist es einfach wichtig ob sie sich öffnen lässt. Was ja automatisch impliziert, dass die Datei da ist und so. So klicke ich mich 6 Stunden am Stück, 3 Stunden die Woche durch eine nie endende Liste. Es sind by the way 560GB mit insgesamt 1,7 Millionen Dateien. Ja klar könnte ich diesen Job stumpf machen, mich bezahlen lassen, nichts lernen und am Ende mit einer Sehnenscheidentzündung das Unternehmen verlassen. Hab ich aber keinen Bock drauf. Also habe ich meinen IT Boss gefragt, der selbst nicht programmieren kann, ob ich einen Teil meiner Zeit an einem Programm arbeiten darf. Ich darf und jetzt sitze ich da. Ich mag es mich mit Programmieren auseinanderzusetzen. Es ist ein kleines Hobby von mir, aber ich stehe im Vergleich zu einem wirklichen Programmierer in den Kinderschuhen.

Ich habe mir nun überlegt wie ich das Programm angehen kann und bin zu folgendem Lösungsansat gekommen. Wenn ihr andere Ansätze habt, immer raus damit.

Ich habe das Verzeichnis mit allen Dateien an einem Ort.
Also schreibe ich erstmal ein Programm, welches eine Liste von allen Dateien und ihren Pfaden erstellt. Das ist bereits erledigt. Den Link zum Code füge ich euch gerne unten ein.
Danach sortiere ich die Dateien nach Endungen und schreibe ein Programm welches jede Datei, wie ein Client mit dem jeweiligen Standardprogramm öffnet. Beispielsweise PDF Dateien mit Adobe Reader, doc mit Word und so weiter.

Was haltet ihr von dieser herangehensweise.
Habt ihr Gegenvorschläge, Nachfragen ?
Ich freue mich auf eure Nachrichten.

CODE zum erstellen einer Liste aller Dateien:
https://0bin.net/paste/z8weDLmSKK-opNyA ... rioFEoTKAF
Jankie
User
Beiträge: 592
Registriert: Mittwoch 26. September 2018, 14:06

Die Liste mit allen Pfaden hast du ja schon. Dann würde ich über alle Elemente dieser Liste iterieren und versuchen diese zu öffnen und zu lesen, wenn das nicht klappt gibt er False zurück. Um welche Dateitypen geht es denn? Nur die oben genannten?
nezzcarth
User
Beiträge: 1764
Registriert: Samstag 16. April 2011, 12:47

Also soweit ich es verstanden habe, ist der Ansatz strukturell ganz okay. Ein Bottleneck gibt es allerdings an der Stelle, wo du die Dateien mit der "Standardanwendung" öffnen möchtest. Denn das dürfte in der Regel ja irgendeine GUI-Software sein, die ggf. weitere Interaktion von dir verlangt (zum Beispiel, weil eine Infobox dir mitteilt, dass die Datei nicht gelesen werden kann). Persönlich würde ich daher so vorgehen, dass ich mir eine Übersicht über die (häufiger gsten) Formate machen würde und dann nach Möglichkeiten suchen würde, diese "headless" zu prüfen. Für Formate wie PDFs gibt es beispielsweise Kommandozeilentools, die du verwenden kannst, für Excel Python-Bibliotheken etc. Du deutest dann die Definition von funktioniert ein bisschen um (externe Software kann sich anders verhalten als das "Original"), aber wenn das ganze dafür dann innerhalb weniger Stunden ohne weitere Interaktion die Aufgabe erfüllt, ist das vielleicht gerechtfertigt.

Außerdem ist die Definition von "funktioniert" nicht wirklich optimal und vom jeweiligen Dateiformat abhängig. Während es eher unwahrscheinlichlich ist, dass eine XML-Datei durch Datenverluste so kaputt geht, dass zum Schluss immer noch parsbares XML herauskommt, kann eine Plaintextdatei, bei der die zweite Hälfte fehlt, geöffnet werden und man muss schon genau hinsehen, um den Fehler zu erkennen.

Das wirklich zuverlässig für beliebige Formate hinzubekommen, halte ich für sehr aufwendig, bis unmöglich, wenn man nicht zufällig irgendwo eine Liste mit Checksummen herumliegen hat.
GotchaInSight
User
Beiträge: 2
Registriert: Freitag 10. Januar 2020, 11:56

An Jankie: Es sind im Grunde alle möglichen Dateien. pdf,doc,dtd,docx,xml,dot, ... die meisten sind alles Textdateien. dot ist eine Audiodatei. Aber davon gibt es nicht viele.
Das Problem ist, ich habe schon defekte Dateien versucht zu öffnen, aber der Fehler wird nicht erkannt. Ich habe in dem verworfenen Programm lediglich den Befehl open verwendet, weil ich einen anderen noch nicht kenne.
Open scheint lediglich auf die Datei zuzugreifen.

An nezzcarth: Ok also ich werde mich daransetzen eine Liste mit den häufigsten Dateiendungen zu erstellen und dann veruschen sie "headless" zu prüfen. Was genau bedeutet es eine Datei "headless" zu prüfen ? Bezieht dieser Vorgang sich auf einen Versuch allgemein auf die Datei zuzugreifen, oder diese wirklich zu öffnen ?
Jankie
User
Beiträge: 592
Registriert: Mittwoch 26. September 2018, 14:06

Um die Dateien mit dem Standartprogramm zu öffnen, ruft man diese am besten mit subprocess.Popen(path, shell=True) auf, allerdings weiß ich nicht was passiert wenn man versucht so fehlerhafte Dateien aufzurufen.
Sirius3
User
Beiträge: 18272
Registriert: Sonntag 21. Oktober 2012, 17:20

@Jankie: für das Standard-Programm benutzt man ["start", path] ohne Shell.

Aber es wäre besser, für jedes Dateiformat einen passenden Parser für Python zu suchen, und dort eventuell noch zusätzliche Checks zu implementieren.
Benutzeravatar
__blackjack__
User
Beiträge: 14051
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@GotchaInSight: Anmerkungen zum Skript: Eingerückt wird in Python mir vier Leerzeichen pro Ebene.

Um das ”=” bei Zuweisungen innerhalb von Argumentlisten kommen keine Leerzeichen. Die beiden Argumente von der Funktion werden in der Funktion überhaupt gar nicht verwendet, dafür stehen da die gleichen Pfade *noch mal* hart kodiert.

Beim Testen ob eine Datei lesbar ist verwendest Du ``with`` aber bei der Ergebnisdatei nicht. Entweder das oder ``try``/``finally`` um das schliessen sicherzustellen.

Das "+" bei den Dateimodi macht keinen Sinn. Warum hast Du das da hingeschrieben? Beim Testen ob man die Dateien zum lesen öffnen kann, würde ich die im Binärmodus öffnen. Hat letztlich wahrscheinlich keinen Effekt aber es dient der Dokumentation dass das beliebige Binärdateien sind. Ich bin auch nicht so wirllich von der sinnhaftigkeit überzeugt. Gibt es denn Dateien die sich nicht öffnen lassen? Und falls ja, warum lassen die sich nicht öffnen?

`f` ist wie die meisten einbuchstabigen Namen kein guter Name. Wenn man `file` meint, sollte man auch `file` schreiben.

Das läuft so nicht weil `os` gar nicht importiert wurde.

Die Ausnahmebehandlung ist zu genereisch und es wird im ``try`` zu viel gemacht. Erst einmal sollte man das auf Ausnahmen eingrenzen die auch wirklich etwas mit der Datei zu tun haben, also zum Beispiel weder `NameError` noch `KeyboardInterrupt` noch `MemoryError` sollten zur Folge haben das da in die Ergebnisdatei geschrieben wird die geprüfte Datei wäre nicht in Ordnung. Und auch das schreiben in die Ergebnisdatei kann zu einer Ausnahme führen, beispielsweise wenn die Platte voll ist, oder es sich um ein Netzlaufwerk handelt das nicht mehr erreichbar ist. Dann macht es wenig sinn zu versuchen in Ergebnisdatei zu schreiben das etwas mit der geprüften Datei nicht stimmt.

Dann ist das Format der Ergebnisdatei nicht robust. Dateinamen können ja zum Beispiel auch Zeilenumbrüche enthalten. Wenn man das Ergebnis in einem Programm weiterverarbeiten möchte, sollte man eine Datei schreiben, aus der man die Daten auch einfach und zuverlässig wieder mit einem Programm auslesen kann. Hier würde sich beispielsweise eine CSV-Datei anbieten, für die es in der Standardbibliothek das CSV-Modul gibt. Ausserdem würde ich vielleicht noch den Grund speichern warum eine Datei nicht geöffnet werden konnte. Die Information bekommt man ja in Form eines Fehlercodes, also warum sollte man die verwerfen.

`os` ist für Pfadkram ein bisschen altmodisch. In neuen Programmen würde ich auf `pathlib` setzen.

Ungetestet:

Code: Alles auswählen

#!/usr/bin/env python3
import csv
import os

PATH = "Z:\\zls_shk"
DUMP_PATH = "C:\\Users\\FrederikSu\\Desktop\\Dump\\Testfile2.csv"


def traverse_and_log():
    with open(DUMP_PATH, "w", encoding="utf-8") as result_file:
        writer = csv.writer(result_file)
        writer.writerow(["state", "error_code", "path"])
        for root, _, files in os.walk(PATH, topdown=False):
            for name in files:
                full_fname = os.path.join(root, name)
                print(full_fname)
                try:
                    with open(full_fname, "rb"):
                        pass
                except OSError as error:
                    error_code = error.errno
                else:
                    error_code = None

                writer.writerow(
                    ("OK" if error_code is None else "NOT OK"),
                    ("" if error_code is None else str(error_code)),
                    full_fname,
                )


if __name__ == "__main__":
    traverse_and_log()
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
nezzcarth
User
Beiträge: 1764
Registriert: Samstag 16. April 2011, 12:47

GotchaInSight hat geschrieben: Freitag 10. Januar 2020, 13:29 An nezzcarth: Ok also ich werde mich daransetzen eine Liste mit den häufigsten Dateiendungen zu erstellen und dann veruschen sie "headless" zu prüfen. Was genau bedeutet es eine Datei "headless" zu prüfen ? Bezieht dieser Vorgang sich auf einen Versuch allgemein auf die Datei zuzugreifen, oder diese wirklich zu öffnen ?
Ich meinte mit "headless" in dem Kontext nur, dass ich persönlich nicht versuchen würde, die jeweiligen Dateien mit der "Standardanwendung" zu öffnen, sondern eben eine Alternative Verifizierungsmethode zu suchen, die ohne Interaktion auskommt. Wenn du beispielsweise jede MS Office Datei mit Word/Excel/PowerPoint/... öffnen lässt, hast du dir zunächst eben nur das Öffnen der Datei gespart. Ab da musst du dann ja selbst übernehmen, also z.B. Popups lesen und schließen usw. Solche Anwendungen brauchen ja in der Regel auch etwas länger zum Starten, als etwa ein Kommanozeilen-Werkzeug. GUI Anwendungen sind meiner Meinung nach für solche Zwecke daher weniger gut geeignet.

Allerdings gibt es -- um beim Beispiel zu bleiben -- für Office Dateien auch andere Möglichkeiten, diese zu verifizieren, die ohne Interaktion auskommen. 'docx/xlsx/pptx' etwa sind technisch gesehen eigentlich nur ZIP-Files mit einer spezifischen internen Struktur, und wenn man deren Integrität prüfen will (was gerade bei ZIP-Files ganz gut funktioniert, da sie für solche Fälle spezielle Infos wie Checksummen enthalten), geht das aus Python heraus mit dem eingebauten Zip-Modul. Vergleichbare Möglichkeiten gibt es auch für andere Formate, wo du entweder auf eine Python-Bibliothek zum Einlesen oder zumindest ein externes Kommandozeilen-Tool zurückgreifen kannst. XML-basierte Formate kannst du durch einen XML-Parser schicken, PDFs zum Beispiel mit 'pdfinfo' (gibt vielleicht auch etwas bessers) prüfen, usw.

Daher würde ich vor der eigentlichen Arbeit eine Erhebung machen, welche Formate wie oft vorkommen. Auf der Basis kannst du dann eine Abschätzung machen, ob es sich, gemessen am notwendigen Aufwand, für die einzelnen Formate lohnt, einen automatischen Check zu implementieren, oder ob es schneller geht, diese Dateien per Hand zu prüfen. Wenn du pro Datei per Hand (sehr optimistisch geschätzt) 15 Sekunden brauchst, bist du mit den 1.7 Files etwa 295 Tage beschäftigt.

EDIT: Noch eine Nebenbemerkung: Dateiendungen sind nur Heuristiken. Sie mögen zu 98% zutreffen, aber manchmal halt auch nicht. Als Alternative kann man zum Beispiel 'file'/'libmagic' verwenden. Das dauert viel länger, da es sich den Dateiinhalt (teilweise) ansieht, ist aber vielleicht für einige hartnäckige Fälle hilfreich.
Benutzeravatar
DeaD_EyE
User
Beiträge: 1239
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

Bilder könntest du damit überprüfen: https://pillow.readthedocs.io/en/5.1.x/ ... rmats.html
Excel Dateien: https://openpyxl.readthedocs.io/en/stable/

Du müsstest quasi für jeden möglichen Dateitypen ein Modul finden, dass diesen parsen kann und auch meckert, wenn das Format nicht valide ist.
Ich würde anfangen mich erst mal nur auf einen bestimmten Dateitypen zu konzentrieren. Du kannst ja z.b. erstmal mit Excel probieren.
Ich denke mal, dass das mit die wichtigsten Dateien sein werden.
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
Antworten