Seite 1 von 1
Bilder sortieren funktioniert nur ein paar Mal, dann ist Schluss
Verfasst: Freitag 13. Mai 2016, 16:46
von harlekyn
Guten Abend,
leider versuche ich vergebens ein Problem in meinem Skript zu beheben. Könntet ihr mir vielleicht einen kleinen Denkanstoß zu kommen lassen?
Funktionsbeschreibung:
Blöd wie ich bin habe ich meine Bilder - Festplatte gelöscht und danach versucht alles wieder herzustellen. Dies hat auch zum Größtenteil geklappt, aber alle Bilder hießen jetzt nach folgendem Prinzip 686468416321.jpg ... Faul wie man nun mal bei 1000+ Bildern ist, dachte ich mir, dass ich einfach die Bilder von Python sortieren lasse.... Funktioniert so weit ganz gut.... So ist der Ablauf:
Ablauf:
-> Skript rennt durch alle Ordner und Unterordner von dem Pfad in der Settings.ini
-> Sucht und findet .jpg-Dateien ( Hoffe auch irgendwann PNG / AVI / etc hinzuzufügen)
-> Schaut in den EXIF - Metadaten ( Python-Library: pyexiv2 ) und wandelt das DateTime um in einen lesbaren String
-> Nennt das Bild um ( z.B. 2016-05-13-17-34-22.jpg ) und verschiebt es in den Skript-Ordner
-> Rennt weiter zum nächsten, bis alle jpgs weg sind
Problem:
Dies funktioniert bei dem Beispiel Ordner (gepackt im Beispiel.7z) und zuhause auch bei ein paar Bildern. Beim Beispiel-Ordner einwandfrei, aber zuhause nur knapp 20 Bilder lang und dann war Schluss. Andere Ordner / Bilder entfernen haben leider nicht geholfen. Frage ist nun, habe ich einen Denkfehler? :K
Könntet ihr mir helfen? Gerne nehme ich auch Verbesserungen für meinen Code entgegen. Ach ja, das ganze soll auf Windows 7 laufen.
URL zum Github Projekt:
https://github.com/harlekyn/Py_Bilder
Beste Grüße und euch noch nen schönes Wochenende!
Euer harlekyn
PS: Ich bitte von Sprüchen wie "Google doch" und anderen Sprüchen abzusehen.
Code: Alles auswählen
import os
import re
import shutil
import pyexiv2 # ExIf Daten auslesen
import ConfigParser
#
## Ort auslesen
config = ConfigParser.ConfigParser()
config.read('settings.ini')
ort = config.get('Allgemein', 'Ort')
typ = config.get('Allgemein', 'Typ')
print '[*] Einstellung: ' + ort
print '[*] Einstellung: ' + typ
#
## Funktion: Umbenennen
def umbenennen(original):
metadata = pyexiv2.ImageMetadata(original)
metadata.read()
tag = metadata['Exif.Image.DateTime']
date_pic = tag.value
neu = '20' + date_pic.strftime("%y-%m-%d-%H-%M-%S")
try:
os.rename(original, neu + '.jpg')
except OSError as e:
print ('[-] Error: %s' % e)
try:
os.rename(original, neu + '_Copy.jpg')
except OSError as e:
print ('[-] 2.Error: %s' % e)
try:
os.rename(original, neu + '_Copy2.jpg')
except OSError as e:
print ('[-] 3.Error: %s' % e)
#
## Ordner durchsuchen
for root, path, files in os.walk(ort):
for filename in files:
string1 = str(filename) # Umwandeln in String
string2 = re.sub(r'\'', '', string1) # Entfernen von '
string3 = re.sub(r'\[', '', string2) # Entfernen von [
string4 = re.sub(r'\]', '', string3) # Entfernen von ]
if string4.endswith(typ):
datei = os.path.join(root, string4)
print '[*] Datei: ' + datei
umbenennen(datei)
Re: Bilder sortieren funktioniert nur ein paar Mal, dann ist Schluss
Verfasst: Freitag 13. Mai 2016, 17:12
von DasIch
harlekyn hat geschrieben:Beim Beispiel-Ordner einwandfrei, aber zuhause nur knapp 20 Bilder lang und dann war Schluss.
Was meinst du mit Schluss?
Re: Bilder sortieren funktioniert nur ein paar Mal, dann ist Schluss
Verfasst: Freitag 13. Mai 2016, 21:10
von Sirius3
@harlekyn: Was heißt "war Schluß"? Gib es eine Fehlermeldung? Sind alle Dateien abgearbeitet?
In Deiner settings.ini sollten nur einfache Backslashes stehen. Das gibt es ja keine Escape-Sequenzen. Was passiert, wenn es sich um keine gültige Jpeg-Datei handelt oder Metadaten fehlerhaft sind? Da solltest Du entsprechende Exceptions abfangen, dass das Programm nach einer Meldung mit der nächsten Datei weiter machen kann. Bei strftime gibt es %Y damit das Programm im nächsten Jahrhundert auch noch läuft. Deinen try-except-Baum beim Umbenennen solltest Du durch eine Schleife ersetzen, dann kannst Du auch bis _copy34982 gehen. Wenn Du den Typ schon variabel angibst, dann sollte der auch beim Umbenennen benutzt werden. Man kann auch Variablen mehrfach verwenden. Das durchnummerieren von nichtssagenden Variablennamen (string1, ...) macht die Sache nicht besser. filename ist bereits ein String und wenn er komische Zeichen wie Eckige Klammern enthält, sollte man die nicht entfernen, denn sonst ist das kein gültiger Dateiname mehr.
Re: Bilder sortieren funktioniert nur ein paar Mal, dann ist Schluss
Verfasst: Freitag 13. Mai 2016, 23:47
von harlekyn
Entschuldigung, hatte vergessen den Fehlerlog einzubinden.
Hier der Log:
Code: Alles auswählen
[+] Datei: C:\\Program Files\\2\\recup_dir.636\f2498104782.jpg
Traceback (most recent call last):
File "C:\Users\xxx\Desktop\Py_Bilder\bilder.py", line 58, in <module>
umbenennen(datei)
File "C:\Users\xxx\Desktop\Py_Bilder\bilder.py", line 27, in umbenennen
tag = metadata['Exif.Image.DateTime']
File "C:\Python27\lib\site-packages\pyexiv2\metadata.py", line 209, in __getitem__
return getattr(self, '_get_%s_tag' % family)(key)
File "C:\Python27\lib\site-packages\pyexiv2\metadata.py", line 169, in _get_exif_tag
_tag = self._image._getExifTag(key)
KeyError: 'Tag not set'
Das komische ist ja das es vorher funktioniert hat und erst nach ca 20 Stk. ging es dann gar nicht mehr. Das Bild kann ich mit einem EXIF Tool auch lesen, sprich es gibt ein Datum... Zusätzlich geht es dann bei den Bildern, die vorher funktioniert haben auch nicht mehr. Ist das Skript vielleicht zu schnell? Kurze Atempause einfügen?
@Sirius3:
Dank dir, ich vermerke mir die Verbesserungen und korrigiere sie.
Re: Bilder sortieren funktioniert nur ein paar Mal, dann ist Schluss
Verfasst: Freitag 13. Mai 2016, 23:51
von DasIch
Der Fehler sagt dir doch recht eindeutig dass das Bild kein Datum hat, zumindest nicht unter dem Namen den du erwartest.
Re: Bilder sortieren funktioniert nur ein paar Mal, dann ist Schluss
Verfasst: Freitag 13. Mai 2016, 23:53
von harlekyn
Das komische ist aber, dass die anderen dann auch nicht mehr funktionieren und halt das ein reines EXIF Programm alle benötigten Daten anzeigt.
Alle nachfolgen Bilder klappen dann auch nicht mehr.
Re: Bilder sortieren funktioniert nur ein paar Mal, dann ist Schluss
Verfasst: Samstag 14. Mai 2016, 10:28
von kbr
harlekyn hat geschrieben:Das komische ist aber, dass die anderen dann auch nicht mehr funktionieren und halt das ein reines EXIF Programm alle benötigten Daten anzeigt.
Alle nachfolgen Bilder klappen dann auch nicht mehr.
Was auch immer 'nicht mehr funktionieren' und 'klappt nicht' im Detail bedeuten mögen, es schaut so aus, als ob Deine Methode an die EXIF Daten zu gelangen, fehlerhaft ist. Kurzes googeln führt schnell zu der Erkenntnis, dass die von Dir benutze Library eine Deprecation Warning aufweist und nicht mehr weiter entwickelt wird. Vielleicht solltest Du es mit 'pillow' versuchen. Ein zweites kurzes googeln mit den Stichworten 'pillow' und 'exif' führt jedenfalls recht schnell zu Treffern.
Re: Bilder sortieren funktioniert nur ein paar Mal, dann ist Schluss
Verfasst: Samstag 14. Mai 2016, 10:53
von harlekyn
kbr hat geschrieben:Was auch immer 'nicht mehr funktionieren' und 'klappt nicht' im Detail bedeuten mögen, es schaut so aus, als ob Deine Methode an die EXIF Daten zu gelangen, fehlerhaft ist.
Ich hatte oben den Fehlerlog gepostet, aber ja, es wunderte mich nur das die Bilder vorher funktionieren, dann nach dem Fehler aber leider nicht mehr.
kbr hat geschrieben:Kurzes googeln führt schnell zu der Erkenntnis, dass die von Dir benutze Library eine Deprecation Warning aufweist und nicht mehr weiter entwickelt wird. Vielleicht solltest Du es mit 'pillow' versuchen. Ein zweites kurzes googeln mit den Stichworten 'pillow' und 'exif' führt jedenfalls recht schnell zu Treffern.
Danke für den Tipp schaue ich mir mal an. Stackoverflow und co via Google hatten immer PIL oder PYEXIFV2 empfohlen. Pillow hingegen hatte ich nicht gefunden, schaue es mir auf deinen Hinweis dann mal an.
Re: Bilder sortieren funktioniert nur ein paar Mal, dann ist Schluss
Verfasst: Samstag 14. Mai 2016, 11:00
von BlackJack
@harlekyn: Daran das ein Programm nachdem es mit einer Ausnahme abbricht, nicht mehr weiterläuft, ist gar nichts komisch.
Und wenn eine andere Software einen Zeitstempel bei dem betroffenen Bild anzeigt, bist Du sicher das es das 'Exif.Image.DateTime'-Tag ist, was dort angezeigt wird? Es gibt in EXIF noch andere Tags um Datum und Zeit zu speichern. Lass Dir bei dem betroffenen Bild doch einfach mal alle Tags ausgeben.
Re: Bilder sortieren funktioniert nur ein paar Mal, dann ist Schluss
Verfasst: Samstag 14. Mai 2016, 11:05
von harlekyn
BlackJack hat geschrieben:@harlekyn: Daran das ein Programm nachdem es mit einer Ausnahme abbricht, nicht mehr weiterläuft, ist gar nichts komisch.
Und wenn eine andere Software einen Zeitstempel bei dem betroffenen Bild anzeigt, bist Du sicher das es das 'Exif.Image.DateTime'-Tag ist, was dort angezeigt wird? Es gibt in EXIF noch andere Tags um Datum und Zeit zu speichern. Lass Dir bei dem betroffenen Bild doch einfach mal alle Tags ausgeben.
Danke, werde ich mal machen! Ich muss das Bild mal genauer untersuchen.
Re: Bilder sortieren funktioniert nur ein paar Mal, dann ist Schluss
Verfasst: Samstag 14. Mai 2016, 12:04
von BlackJack
@harlekyn: Noch ein paar Anmerkungen zu den Quelltext:
`re` und `shutil` werden importiert, aber nicht verwendet.
Auf Modulebene sollten keine Variablen und kein Hauptprogramm stehen. Das steht üblicherweise in einer Funktion die `main()` heisst.
Kommentare sollten dem Leser einen Mehrwert zum Code bieten. Vor einer Funktionsdefinition zu kommentieren ``# Funktion: funktionsname`` bringt dem Leser nichts. Faustregel: Kommentare sollten nicht beschreiben *was* passiert, denn das steht da ja schon als Code, sondern *warum* es so passiert wie der Code das macht, sofern das nicht offensichtlich ist.
`path` ist in der Schleife im Hauptprogramm der falsche Name. Da wird nicht ein Pfad dran gebunden sondern potentiell viele Verzeichnisnamen. `files` und `datei` sind auch nicht ganz passend, denn es handelt sich nicht um Dateiobjekte sondern um Datei*namen*.
Man könnte dann ungefähr bei so etwas heraus kommen (ungetestet):
Code: Alles auswählen
#!/usr/bin/env python
# coding: utf8
from __future__ import absolute_import, division, print_function
import ConfigParser
import os
import pyexiv2
def rename(old_path, typ):
metadata = pyexiv2.ImageMetadata(old_path)
metadata.read()
new_filename = format(
metadata['Exif.Image.DateTime'].value, '%Y-%m-%d-%H-%M-%S'
)
for i, copy_name in enumerate(['', '_Copy', '_Copy2'], 1):
try:
os.rename(old_path, '{}{}{}'.format(new_filename, copy_name, typ))
break
except OSError as error:
print('[-] {0}.Error: {1}'.format(i, error))
def main():
config = ConfigParser.ConfigParser()
config.read('settings.ini')
base_path = config.get('Allgemein', 'Ort')
extension = config.get('Allgemein', 'Typ')
print('[*] Einstellung:', base_path)
print('[*] Einstellung:', extension)
for root, _, filenames in os.walk(base_path):
for filename in filenames:
if filename.endswith(extension):
path = os.path.join(root, filename)
print('[*] Datei:', path)
try:
rename(path, extension)
except Exception as error:
print('[-]', error)
if __name__ == '__main__':
main()
Re: Bilder sortieren funktioniert nur ein paar Mal, dann ist Schluss
Verfasst: Sonntag 15. Mai 2016, 11:06
von harlekyn
BlackJack hat geschrieben:@harlekyn: Noch ein paar Anmerkungen zu den Quelltext:
`re` und `shutil` werden importiert, aber nicht verwendet.
Auf Modulebene sollten keine Variablen und kein Hauptprogramm stehen. Das steht üblicherweise in einer Funktion die `main()` heisst.
Kommentare sollten dem Leser einen Mehrwert zum Code bieten. Vor einer Funktionsdefinition zu kommentieren ``# Funktion: funktionsname`` bringt dem Leser nichts. Faustregel: Kommentare sollten nicht beschreiben *was* passiert, denn das steht da ja schon als Code, sondern *warum* es so passiert wie der Code das macht, sofern das nicht offensichtlich ist.
`path` ist in der Schleife im Hauptprogramm der falsche Name. Da wird nicht ein Pfad dran gebunden sondern potentiell viele Verzeichnisnamen. `files` und `datei` sind auch nicht ganz passend, denn es handelt sich nicht um Dateiobjekte sondern um Datei*namen*.
Man könnte dann ungefähr bei so etwas heraus kommen (ungetestet):
Vielen Dank, werde ich mir mal zu gemüte führen. Bisher habe ich noch nichts wegen der Main-Funktion gelesen, außer halt c++. Rein optisch halber oder ein muss? Die Kommentare haben für mich in der Hinsicht eigentlich nur eine schnelle Übersicht geboten, wo fängt was an. Ansonsten schreibe ich bei Bedarf sie einfach dahinter, siehe Import. re und shutil waren noch "import-Leichen" hatte sie wegen PIL noch drin, mein Fehler sie rauszunehmen.
Vielen Dank nochmal, werde mich bessern!
Re: Bilder sortieren funktioniert nur ein paar Mal, dann ist Schluss
Verfasst: Sonntag 15. Mai 2016, 11:36
von __deets__
main-Funktionen sind nicht reine Optik. Der Grund ist, dass aus Skripten auch Module werden koennen, also von ihnen importiert wird.
Eine nicht durch das idiom
geschuetzte Ausfuehrung wuerde dann einen Seiteneffekt (naemlich die Ausfuehrung) bedeuten - das will man aber dann nicht.
Re: Bilder sortieren funktioniert nur ein paar Mal, dann ist Schluss
Verfasst: Sonntag 15. Mai 2016, 11:39
von snafu
harlekyn hat geschrieben:Bisher habe ich noch nichts wegen der Main-Funktion gelesen, außer halt c++. Rein optisch halber oder ein muss?
Wie du vielleicht schon selber bemerkt hast, laufen Python-Programme auch ohne `main()`-Funktion, zumal der Python-Compiler überhaupt keine Funktionalität zum selbständigen Erkennen von `main()` eingebaut hat. In vielen Programmen wird aber dennoch eine `main()`-Funktion als Einstieg genutzt. Oft findet man die Umsetzung dann in dieser Form:
Sieht anfangs etwas verwirrend aus. Es sorgt dafür, dass in einem Programm, welches von der Kommandozeile gestartet wird (``python meinprog.py``), automatisch die `main()`-Funktion aufgerufen wird. Grund: Programme, die so ausgeführt werden, haben automatisch den Wert "__main__" für ihr `__name__`-Attribut.
Der eigentliche Vorteil zeigt sich, wenn man den Code als Modul importiert (``import meinprog``). Durch den Einsatz der `main()`-Funktion in Verbindung mit dem gezeigten `if`-Konstrukt kommt es dann nämlich *nicht* zum automatischen Aufrufen des Codes, da dort ``__name__ == '__main__'`` einen anderen Wert hat.
Somit könnte man nach dem Importieren z.B. einzelne Funktionen des Moduls testen und hat selber die Kontrolle darüber, wann welcher Code ausgeführt wird. Manchmal sind Module auch so gestaltet, dass sie aus Python heraus wie eine Bibliothek genutzt werden können und dass sie in der `main()`-Funktion zusätzlich einen CLI-Parser einsetzen, um die Funktionalität auch über Optionen auf der Kommandozeile nutzbar zu machen. Da wäre es wenig hilfreich, wenn der CLI-Parser auch bei einem Import anspringen würde.
Re: Bilder sortieren funktioniert nur ein paar Mal, dann ist Schluss
Verfasst: Sonntag 15. Mai 2016, 14:14
von BlackJack
@harlekyn: Keine Variablen auf Modulebene und damit auch das Hauptprogramm in einer Funktion würde ich als „muss” ansehen. Es ist übersichtlicher (und damit ist nichts „optisches“ gemeint, es geht nicht um „schön“, sondern um leicht(er) verständlich) und sicherer, weil es nicht passieren kann, dass man aus versehen Werte von aussen in Funktionen oder Methoden benutzt auf die diese eigentlich so nicht zugreifen sollten.
Zudem kann man mit dem ``if __name__ …`` am Ende dafür sorgen, dass man das Modul importieren kann, ohne dass das Programm automatisch gleich abläuft. Das ist zum einen zur Fehlersuche nützlich, weil man ein Modul dann in einer Python-Shell importieren, und einzelne Funktionen oder Klassen live ausprobieren kann, zum anderen erwarten dieses effektfreie Importieren einige Werkzeuge zur statischen Analyse, Dokumentationsgenerierung, und welche die (Unit-)Tests zusammensammeln und dann ausführen.
Re: Bilder sortieren funktioniert nur ein paar Mal, dann ist Schluss
Verfasst: Dienstag 17. Mai 2016, 03:36
von harlekyn
Vielen Dank an alle für die Erklärung! Ich werde es mir merken für die Zukunft.
Re: Bilder sortieren funktioniert nur ein paar Mal, dann ist Schluss
Verfasst: Dienstag 17. Mai 2016, 08:55
von snafu
snafu hat geschrieben:Der eigentliche Vorteil zeigt sich, wenn man den Code als Modul importiert (``import meinprog``). Durch den Einsatz der `main()`-Funktion in Verbindung mit dem gezeigten `if`-Konstrukt kommt es dann nämlich *nicht* zum automatischen Aufrufen des Codes, da dort ``__name__ == '__main__'`` einen anderen Wert hat.
Sollte natürlich heißen:
"(...) da dort `__name__` einen anderen Wert hat."