Seite 1 von 1

invalid syntax bei def

Verfasst: Donnerstag 6. Juli 2017, 00:43
von Lou Cyphr3
Hallo,

ich bin ein python-noob. Ich nutze Python3 und probiere immer mal mit charm und Ipython rum.
Nun habe ich mir gedacht ich probiere mal ein Script aus, welches ich in den Weiten des Internets gefunden habe, nachdem
ich mir schon ein wenig die Basics gab.

So jetzt ist mein Problem, dass es mir immer ein invalid syntax ausgibt, obwohl ich meines erachtens keinen drin habe.

Code: Alles auswählen

import argparse
from PIL import Image
from PIL.exifTags import TAGS

def getMetaData(imagename, out):
    try:
        metaData ={}

        imgFile = image.open(imgname)
        print('metadaten ...')
        info = imgFile._getexif()
        if info:
            print('metadaten gefunden...')
            for (tag, value) in info.items():
                tagname = TAGS.get(tag, tag)
                metaData[tagname] = value
                if not out:
                    print(tagname, value)
                    if out:
                        print('ausgeben der Daten...')
                        with open(out, 'w') as f:
                            for (tagname, value) in metaData,items():
                                f.write(str(tagname+'\t'+\
                                            str(value)+'\n')
    except:

def main():

        parser = argparse.ArgumentParser()
        parser.add_argument('img', help='name of the file' )
        parser.add_argument('--ouput','-o', help='dump data out the file')
        args = parser.parse_args()
        if agrs.img:
            getMetaData(args.img, args.output)
        else:
            print(parser.usage
if_name_== '_main_':
        main()
als Fehler wird mir in diesem Fall "
def Main(): line 26
^
SyntaxError: invalid syntax

Process finished with exit code 1" ausgegeben. Ich hab auch schon sämtliche Variationen mit und ohne Klammer; : etc. ausprobiert.

Kann mir wer einen Hinweis geben?

Re: invalid syntax bei def

Verfasst: Donnerstag 6. Juli 2017, 06:23
von Sirius3
@Lou Cyphr3: der Code ist unvollständig. In Python gibt es eine Namenskonvention, an die Du Dich nicht hältst. Variablen und Funktionen werden klein_mit_unterstrich geschrieben, also get_meta_data. Der Name der Funktion ist aber irreführend, da gar nichts geholt (get) wird, sondern nur etwas in eine Datei geschrieben wird. Blöcke sollten nicht so tief geschachtelt werden. Du hast 8 (in Worten acht) Ebenen. Das dass zu viel ist, sieht Du daran, dass das write, eigentlich ganz kurz ist, aber doch in zwei Zeilen umgebrochen werden muß. Um dies zu verhindern, teilt man solche Stellen in mehrere Funktionen auf.

wenn keine exif-Daten gefunden werden, also info leer ist, wird nichts gemacht; das ist überraschend, und Überraschungen mögen Programmierer nicht. Hier solltest Du mit einem Fehler abbrechen. metaData werden in Zeile 7 initialisiert, aber erst in Zeile 16 verwendet. So weit voneinander entfernte Verwendung macht Code unleserlich. Das Initialisieren gehört direkt vor die for-Schleife.

Danach stimmt etwas mit der Einrückung nicht mehr. In einem Zweig, wo out unwahr ist, wird nur etwas gemacht, wenn out wahr ist, ergo nie. Das `if out` gehört logischerweise auf die gleiche Stufe wie das for. Damit reduziert sich die maximale Einrücktiefe auf 6, was aber immer noch zu viel ist.

In Zeile 22 steht ein Komma, wo ein Punkt sein müßte.
Zeile 23: Strings sollte man nicht mit + zusammenstückeln, das ist kaum lesbar, so dass einem auch leicht eine fehlende schließende Klammer übersieht; benutze "{}\t{}\n".format(tagname, value) oder gleich das csv-Modul, wenn es sich hier um ein csv-Dateiformat handelt.

Nach except bricht die Funktion ab. Da fehlt was. Nackte excepts sollte man nie benutzen, denn das einzige, was man an dieser Stelle sinnvoll behandeln könnte, wäre, den Fehler an die darüberliegende Funktion weiterzureichen. Dann kann das try-except aber gleich weg.

Die Zeilen in main sind zu weit eingerückt. In Zeile 33 ist ein Tippfehler. In Zeile 36 fehlt eine schließende Klammer, In Zeile 37 fehlen ein Leerzeichen und 4 Unterstriche. Zeile 38 ist zu weit eingerückt.

Mach Dich mit der Python-Syntax vertraut, die Du benutzt. Wenn Du ein try-except findest, ließ nach, was Exception-Handling ist, und wie man es benutzt. Achte auf Klammern und Schreibung. Versuche das Programm Zeile für Zeile selbst nachzuvollziehen, was es macht und ob das sinnvoll ist.

Re: invalid syntax bei def

Verfasst: Donnerstag 6. Juli 2017, 08:48
von BlackJack
Da lauern auch noch mehr Fehler wenn man die beseitigt hat, die ins Auge fallen:

Code: Alles auswählen

In [1]: from PIL.exifTags import TAGS
---------------------------------------------------------------------------
ImportError                               Traceback (most recent call last)
<ipython-input-1-7b5951e10241> in <module>()
----> 1 from PIL.exifTags import TAGS

ImportError: No module named exifTags
Ich wäre auch vorsichtig eine nicht zur öffentlichen API gehörende Methode zu verwenden. Der Grund dafür dürfte folgender Kommentar im Quelltext sein:

Code: Alles auswählen

def _getexif(self):
    # Extract EXIF information.  This method is highly experimental,
    # and is likely to be replaced with something better in a future
    # version.
In diesem experimentellen Stadium ist die Funktion schon seit einer Ewigkeit.

Re: invalid syntax bei def

Verfasst: Donnerstag 6. Juli 2017, 08:59
von Melewo
Bei mir wird in PIL.ExifTags das E wohl groß geschrieben.
Und wo soll imgname in imgFile = image.open(imgname) herkommen?
Aus dem Funktionskopf zumindest nicht, denn da steht imagename und kommt nicht mehr in der Funktion vor.

Re: invalid syntax bei def

Verfasst: Donnerstag 6. Juli 2017, 14:16
von Melewo
So funktioniert es zumindest bei mir mit einem Testbild. with open() war zu tief eingerückt und hätte bei jeder Runde der ersten for-Schleife arbeiten müssen. 3 mal NUL sind noch als Steuerzeichen in der "testfile.txt" enthalten, da müsste vorher noch etwas passieren. Weiß nicht, wie sich das mit den Tag-Namen verhält, bei mir haben zumindest diese beiden gestört.

Code: Alles auswählen

from PIL import Image
from PIL.ExifTags import TAGS

def get_meta_data(imagename, textfile = None):
    try:   
        imagefile  = Image.open(imagename)
        image_info = imagefile._getexif()
        meta_data  = {}    
        
        if image_info:
            for tag, value in image_info.items():
                tagname = TAGS.get(tag)
                if (tagname != "UserComment" and 
                        tagname != "ComponentsConfiguration"):
                    meta_data[tagname] = value
                    
            print(meta_data)  
                    
            if textfile is not None:
                with open(textfile, "w") as datei:
                    for tag, wert in meta_data.items():
                        datei.write('{0}\t{1}\n'.format(tag, str(wert)))

    except:
        print("Fehler!")

imagename = "altmaerkische.jpg" 
textfile  = "testfile.txt"

get_meta_data(imagename, textfile)

Re: invalid syntax bei def

Verfasst: Donnerstag 6. Juli 2017, 14:33
von Sirius3
@Melewo: das try-except ist auch bei Dir falsch; weg damit! Die Bedingung in Zeile 13 kann man besser mit `not in` schreiben. str in Zeile 22 ist unnötig.

Re: invalid syntax bei def

Verfasst: Donnerstag 6. Juli 2017, 15:16
von Melewo
Sirius3 hat geschrieben:@Melewo: das try-except ist auch bei Dir falsch; weg damit!
Das dachte ich mir beinahe, weil ich sonst noch nie eine verwendet habe, nur dieses Mal da stehen ließ. Und als ich dann schon gepostet hatte, fragte ich mich anschließend, ob diese Zeile

Code: Alles auswählen

meta_data[tagname] = value
nicht so besser ausgesehen hätte.

Code: Alles auswählen

meta_data.update({tagname : value})
Oder?

Re: invalid syntax bei def

Verfasst: Donnerstag 6. Juli 2017, 15:18
von BlackJack
@Melewo: Nein überhaupt nicht. Das ist mir an anderer Stelle bei Dir auch schon aufgefallen. Warum sollte es besser zu sein ein Wörterbuch mit einem Schlüssel/Wert-Paar zu erstellen, damit das andere Wörterbuch zu aktualisieren, und dann das Wörterbuch wieder zu verwerfen statt einfach direkt dem Schlüssel einen Wert zuzuweisen?

Re: invalid syntax bei def

Verfasst: Donnerstag 6. Juli 2017, 15:41
von Melewo
Ok, so wie Du es beschreibst leuchtet es mir ein, dann werde ich das andere Script auch noch einmal in diesem Punkt überarbeiten.

Code: Alles auswählen

from PIL import Image
from PIL.ExifTags import TAGS
 
def get_meta_data(imagename, textfile = None):
    imagefile  = Image.open(imagename)
    image_info = imagefile._getexif()
    meta_data  = {}    
   
    if image_info:
        for tag, value in image_info.items():
            tagname = TAGS.get(tag)
            if ("UserComment" not in tagname and
                    "ComponentsConfiguration" not in tagname):
                meta_data[tagname] = value
               
        print(meta_data)  
               
        if textfile is not None:
            with open(textfile, "w") as datei:
                for tag, wert in meta_data.items():
                    datei.write('{0}\t{1}\n'.format(tag, str(wert)))
 
imagename = "altmaerkische.jpg"
textfile  = "testfile.txt"
 
get_meta_data(imagename, textfile)

Re: invalid syntax bei def

Verfasst: Donnerstag 6. Juli 2017, 15:45
von BlackJack
@Melewo: Du hast beim `get()` jetzt `tag` nicht noch einmal als zweites Argument übergeben. Damit bildest Du Tags für die es keinen Namen gibt, alle auf den Schlüssel `None` ab, womit Informationen verloren gehen können.

Re: invalid syntax bei def

Verfasst: Donnerstag 6. Juli 2017, 15:56
von Melewo
Habe das Testbild jetzt mit und ohne zweimal tag bei get aufgerufen und erkenne in der Ausgabe keinen Unterschied.

[codebox=text file=Unbenannt.txt]Make Canon
Model Canon EOS 450D
Orientation 1
YCbCrPositioning 1
XResolution (350, 1)
YResolution (350, 1)
ResolutionUnit 2
ExifOffset 219
Software Digital Photo Professional
DateTime 2015:12:29 11:13:49
ExifVersion b'0221'
ShutterSpeedValue (524288, 65536)
DateTimeOriginal 2011:05:01 14:10:59
DateTimeDigitized 2011:05:01 14:10:59
ApertureValue (548864, 65536)
ExposureBiasValue (0, 1)
FlashPixVersion b'0100'
Flash 16
FocalLength (18, 1)
ColorSpace 1
ExifImageWidth 2053
ExifInteroperabilityOffset 943
FocalPlaneXResolution (4272000, 878)
FocalPlaneYResolution (2848000, 584)
SubsecTime 02
SubsecTimeOriginal 02
SubsecTimeDigitized 02
ExifImageHeight 1424
FocalPlaneResolutionUnit 2
ExposureTime (1, 250)
FNumber (18, 1)
ExposureProgram 4
CustomRendered 0
ISOSpeedRatings 200
ExposureMode 0
WhiteBalance 0
SceneCaptureType 0[/code]

Re: invalid syntax bei def

Verfasst: Donnerstag 6. Juli 2017, 16:11
von BlackJack
@Melewo: Nicht alle Bilder haben die gleichen Tags, und es kann eben auch sein, das es welche mit ”unregistrierten” Nummern gibt. Da gibt es IMHO zwei sinnvolle Möglichkeiten mit umzugehen: Entweder filtert man die komplett raus, oder man behält sie mit dem Tag als Schlüssel. Dein Code bildet die alle auf das Schlüssel/Wert-Paar ``(None, value)`` ab, das heisst wenn es mehrere unbekannte gibt, bleibt nur der letzte Wert im Ergebnis übrig und in jedem Fall geht die Tagnummer verloren. Man weiss dann also nicht einmal *was* übrig geblieben ist.

Re: invalid syntax bei def

Verfasst: Donnerstag 6. Juli 2017, 16:15
von Sirius3
@Melewo: das `not in` hast Du jetzt genau falsch umgesetzt.

Code: Alles auswählen

def get_meta_data(imagename, textfile=None):
    imagefile = Image.open(imagename)
    image_info = imagefile._getexif()
    if not image_info:
        raise AssertionError("no exif data found")
    meta_data = {}    
    for tag, value in image_info.items():
        tagname = TAGS.get(tag, tag)
        if tagname not in ["UserComment", "ComponentsConfiguration"]:
            meta_data[tagname] = value
    print(meta_data)  
    if textfile is not None:
        with open(textfile, "w") as datei:
            for tag, wert in meta_data.items():
                datei.write('{}\t{}\n'.format(tag, wert))

Re: invalid syntax bei def

Verfasst: Donnerstag 6. Juli 2017, 16:20
von Melewo
Gut, ich weiß es nun von Dir, dass die Verwendung von

Code: Alles auswählen

tagname = TAGS.get(tag, tag)
durchaus sinnvoll sein kann und wer das Beispiel verwenden und weiter ausbauen möchte, sollte es entsprechend ändern. Meine Editierzeit ist abgelaufen, sonst hätte ich es noch geändert. Sehe gerade, Sirius3 hat es zwischenzeitlich geändert. Aber das mit dem not in tagname hatte bei den Testaufrufen funktioniert, doch so ist es besser.

Re: invalid syntax bei def

Verfasst: Donnerstag 6. Juli 2017, 18:18
von Sirius3
@Melewo: es gibt einen Unterschied zwischen, »ich habe das Gefühl, es funktioniert« und »das Programm ist korrekt«.

Re: invalid syntax bei def

Verfasst: Freitag 7. Juli 2017, 01:22
von Lou Cyphr3
okay, ich werde mir wohl doch nochmal die Basic's ansehen, aber Danke für die rasche Disskusion.
Aber nochmals zu meinen Problemchen mit den Syntax. Ich habe gerade nochmal angefangen bisschen mit der (for)schleife
rum zuspielen.

Code: Alles auswählen

x = ['ja', 'vllt', 'nein']

for w in x:
    print(w)
print('finish')
eigentlich sollte bei diesen simple codeschnippsel nix schief gehen, allerdings gibt er mir mit der Ipython konsole trotzdem
wieder ein Syntax Error aus und zwar beim letzten 'print'. Lass ich es aber über pycharm laufen, funktioniert alles bestens.

Woran liegt das?

Re: invalid syntax bei def

Verfasst: Freitag 7. Juli 2017, 06:14
von Melewo
Dann kopiere die Fehlermeldung, damit die nachvollziehbar oder auswertbar ist.
Bei mir kann ich zumindest nichts sehen, was da einen Fehler auslösen könnte.

Re: invalid syntax bei def

Verfasst: Mittwoch 12. Juli 2017, 19:10
von /me
Lou Cyphr3 hat geschrieben:eigentlich sollte bei diesen simple codeschnippsel nix schief gehen, allerdings gibt er mir mit der Ipython konsole trotzdem
wieder ein Syntax Error aus und zwar beim letzten 'print'.
Wenn das mit der interaktiven Konsole so wie bei IDLE läuft, dann solltest du am Ende des Schleifenrumpfs einmal extra die Eingabetaste drücken bevor du den Code fortsetzt.