glob Dateiname enthält [i-F > re.error

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
GeoPaul
User
Beiträge: 3
Registriert: Donnerstag 20. August 2020, 07:19

Hallo,
Mein erster Post hier im Forum und einer der ganz wenigen überhaupt bislang. Ich bin also nicht wirklich forenerfahren.

Mein erstes wirkliches Pythonprojekt habe ich soweit mit viel trail & (noch mehr) error bislang allein hinbekommen und es tut, was es soll.
Natürlich nicht ganz, sonst würde ich hier nicht schreiben.

Aus einer SQLite Datenbank lese ich, neben einigen anderen Angaben, den Dateinamen eines i.d.R. jpg aus.
Die Bilder/Videos befinden sich in einen Ordner mit diversen Unterordnern und müssen auch nicht zwangsläufig vorhanden sein.
Es können Ordner mit mehreren Tausend Dateien sein. Deswegen dieses Script.

Das funktioniert auch super hiermit:

Code: Alles auswählen

cursor.execute(sql, value)

    abfrage = cursor.fetchall()
    liste1 = []

    for row in abfrage:
        gesuchte_datei = row[1]
        pfad = "G:/Bilder_Videos/**/" + str(gesuchte_datei)
        files = glob.glob(pfad, recursive=True)
        print(gesuchte_datei)  # Rückmeldung (nix für den eigenlichen Code
        if files:
            liste1.extend(row)
            liste1.append(files[0])
        else:
            liste1.append(row)
            liste1.append('nicht vorhanden')

    print(len(abfrage))  # Rückmeldung (nix für den eigentlichen Code)
    print(liste1)
    
Mein Problem ist nun, dass die Dateinamen auch regex-ähnliche Konstrukte enthalten können und mir in bestimmten Fällen dann ein re.error ausgegeben wird.
Im SQLite-Browser habe ich die Dateinamen mal gelöscht und dann lief die Sache auch durch.

Die Listenform habe ich gewählt, da es das erste war, was ich dazu für mich brauchbar gefunden hatte und nachvollziehen konnte.
Ich möchte diese Liste im späteren Verlauf mit dem docx-Modul weiterverarbeiten, was auch schon geklappt hat.

Löschen der Dateinamen in der Datenbank oder auf der Festplatte ist natürlich nur zum Testen eine Option.

Vielen Dank für einen kleinen (oder auch konkreten) Hinweis
Paul aus Lübeck
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

`liste1` ist ein schlechter Variablenname weil zu generisch und die 1 nichtssagend ist.
Du benutzt einmal extend(row) und einmal append(row). Du hast zum Schluß eine Liste, wo immer n Elemente zusammengehören, das ist schlecht, weil schwer weiter zu verarbeiten. Eine Liste enthält immer gleichartige Elemente. Statt "nicht vorhanden" nimmt man als Platzhalter None, für nicht vorhanden und packt das mit row in ein Tuple.
Pfade stückelt man nicht mit + zusammen, sondern benutzt pathlib.Path. glob ist veraltet.
Was soll passieren, wenn die Datei mehrfach gefunden wird?

Code: Alles auswählen

from pathlib import Path
BILDER_PATH = Path("G:/Bilder_Videos")

...

    abfrage = cursor.fetchall()
    datasets_with_filenames = []

    for row in abfrage:
        gesuchte_datei = row[1]
        files = list(BILDER_PATH.rglob(gesuchte_datei))
        if files:
            # take only first file found
            row += (files[0], )
        else:
            # None if file not found
            row += (None, )
        datasets_with_filenames.append(row)
Jetzt ist es natürlich ziemliche Verschwendung, tausende Male die ganzen Verzeichnisse zu durchsuchen, nur im jeweils eine Datei zu finden. Man würde wohl alle Dateien einmal suchen und speichern:

Code: Alles auswählen

    all_filenames = {
        f.name: f
        for f in BILDER_PATH.rglob('*')
    }

    abfrage = cursor.fetchall()
    datasets_with_filenames = []
    for row in abfrage:
        gesuchte_datei = row[1]
        datasets_with_filenames.append(row + (all_filenames.get(gesuchte_datei),))
Im ganzen Code kommen keine regulären Ausdrücke vor, und mit ›[i-F > re.error‹ kann ich auch nichts anfangen. Wie hast Du denn versucht mit regulären Ausdrücken zu arbeiten? Wie sehen diese aus? Wie ist der genaue Fehler inklusive Traceback?
GeoPaul
User
Beiträge: 3
Registriert: Donnerstag 20. August 2020, 07:19

Hallo Sirius3,

Danke für die Antwort und die Hinweise.

Liste wollte ich später dann im überarbeiteten Code ändern.

Die Abfrage ergibt je row
(Typ, Dateiname, Speicherdatum). Als viertes Element soll in der Liste der dazugehörige Dateipfad hinzukommen.
Um diese Klammer aufzulösen und den Pfad an "Position 4" zu bekommen und nicht an 2 habe ich extend(row) gewählt.

Zu deiner Anmerkung zu Mehrfachtreffern: Ich war eigentlich der Meinung durch files[0] hätte ich das gelöst.
Mag Zufall gewesen sein, aber hat geklappt.

Im Code habe ich auch keine regex. Irgendjemand hat halt mal z. b. die Datei "[i-Fehler][1]warum auch immer so einen Dateinamen.jpg" gespeichert.
So steht sie als Dateiname in der Datenbank und auch das gesuchte File ist mit diesem Namen evtl auch auf der Platte.

Wenn so ein Konstrukt vorliegt bricht das Script ab. Auf regex bin ich wegen :
raise source.error(msg, len(this) + 1 + len(that))
re.error: bad character range i-f at position 64
gekommen.

Oder das ganze Traceback?
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\Paul\AppData\Local\Programs\Python\Python39\lib\tkinter\__init__.py", line 1892, in __call__
return self.func(*args)
File "G:\dateisuche\002testen_backup.py", line 76, in curSelect
files = glob.glob(pfad, recursive=True)
File "C:\Users\Paul\AppData\Local\Programs\Python\Python39\lib\glob.py", line 21, in glob
return list(iglob(pathname, recursive=recursive))
File "C:\Users\Paul\AppData\Local\Programs\Python\Python39\lib\glob.py", line 74, in _iglob
for name in glob_in_dir(dirname, basename, dironly):
File "C:\Users\Paul\AppData\Local\Programs\Python\Python39\lib\glob.py", line 85, in _glob1
return fnmatch.filter(names, pattern)
File "C:\Users\Paul\AppData\Local\Programs\Python\Python39\lib\fnmatch.py", line 58, in filter
match = _compile_pattern(pat)
File "C:\Users\Paul\AppData\Local\Programs\Python\Python39\lib\fnmatch.py", line 52, in _compile_pattern
return re.compile(res).match
File "C:\Users\Paul\AppData\Local\Programs\Python\Python39\lib\re.py", line 252, in compile
return _compile(pattern, flags)
File "C:\Users\Paul\AppData\Local\Programs\Python\Python39\lib\re.py", line 304, in _compile
p = sre_compile.compile(pattern, flags)
File "C:\Users\Paul\AppData\Local\Programs\Python\Python39\lib\sre_compile.py", line 764, in compile
p = sre_parse.parse(p, flags)
File "C:\Users\Paul\AppData\Local\Programs\Python\Python39\lib\sre_parse.py", line 948, in parse
p = _parse_sub(source, state, flags & SRE_FLAG_VERBOSE, 0)
File "C:\Users\Paul\AppData\Local\Programs\Python\Python39\lib\sre_parse.py", line 443, in _parse_sub
itemsappend(_parse(source, state, verbose, nested + 1,
File "C:\Users\Paul\AppData\Local\Programs\Python\Python39\lib\sre_parse.py", line 834, in _parse
p = _parse_sub(source, state, sub_verbose, nested + 1)
File "C:\Users\Paul\AppData\Local\Programs\Python\Python39\lib\sre_parse.py", line 443, in _parse_sub
itemsappend(_parse(source, state, verbose, nested + 1,
File "C:\Users\Paul\AppData\Local\Programs\Python\Python39\lib\sre_parse.py", line 598, in _parse
raise source.error(msg, len(this) + 1 + len(that))
re.error: bad character range i-f at position 64
Wenn ich im SQLite-Browser nachsehe, dann ist eben in der Reihenfolge dieser komische Dateiname dran. und mir fiel nix anderes ein, als das der Fehler sein könnte.

Die anderen Vorschläge versuche morgen mal.
Ich hatte zunächst mit os.walk und os.path.join, aber bin bislang nur mit glob.glob zum gewünschten Ergebnis gekommen.

Ich such mir den Namen der speichernden Person aus einer listbox per cursorselection und übergeb diese dann als variable an die abfrage, über die wir jetzt hier sprechen. Läuft.
Die Listbox wird aus der gleichen DB mit einer vorherigen Abfrage gefüllt.

Vielleicht war ich zu schnell zu stolz, das erste Programm(chen) fertig gestellt zu haben. Oder ich hätte alle Personen durchtesten sollen, und nicht nur die ersten 3.

Schönen Fußballabend ?? noch

Paul
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

Das ist halt immer das Problem, wenn wichtige Teile des Programms fehlen. Was steht in sql oder values?

os.walk und os.path.join sind genauso veraltet.

Und Dein geschildertes Problem steht ganz zu Anfang in der Dokumentation zu glob: https://docs.python.org/3/library/glob.html
Wie kann man es da übersehen?
GeoPaul
User
Beiträge: 3
Registriert: Donnerstag 20. August 2020, 07:19

Sirius3,
Sorry für so gar keine Rückmeldung...
Aber ich hab grad ne andere Baustelle. Mein eigentlich so treuer Campingbus und der TÜV mochten sich nicht mehr....

Mit dem Hinweis auf 'Escape' hab ich es aber jetzt hinbekommen und es tut was es soll.
Bis auf eine Fehlermeldung bei pyinstaller.

Grüße
Antworten