Problem beim Umstieg von 2.7 auf 3.2 mit functools.partial

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
mathi
User
Beiträge: 314
Registriert: Dienstag 27. November 2007, 14:30

hallo miteinander,

ich habe im Programm unter Python 2.7 folgendes erstellt (es funktioniert):

Code: Alles auswählen

label2=functools.partial(label,newdir=newdir,newdate=newdate)
unter 2.7 ergibt ein

Code: Alles auswählen

print label2
das Ergebnis

Code: Alles auswählen

<functools.partial object at 0x00000000048ABAE8>
unter 3.2 ergibt das gleiche dann

Code: Alles auswählen

functools.partial(<function label at 0x0000000002E0A840>, newdir='D:\\Projekte\\Bilder\\new', newdate=False)
was mir für die nachfolgende Funktion:

Code: Alles auswählen

            for i in pool.map(label2,([q]*self.anzahl)):       
               self.count+=1
               
dann die Fehlermeldung bringt:
Traceback (most recent call last):
File "D:\Python\Code\pyQT\PySide-Projekt\jpglabel.pyw", line 206, in on_calcbtn_clicked
for i in pool.map(label2,([q]*self.anzahl)):
File "C:\Python33\lib\multiprocessing\pool.py", line 228, in map
return self._map_async(func, iterable, mapstar, chunksize).get()
File "C:\Python33\lib\multiprocessing\pool.py", line 564, in get
raise self._value
AttributeError: 'NoneType' object has no attribute 'dict'
Das ist das Ganze in Kürze. Kann mir dabei bitte jemand helfen??
Falls der Code ausführlicher benötigt wird, kann ich das noch nachreichen :-)

Danke im Voraus
Mathi
BlackJack

@mathi: Ich sehe jetzt nicht dass das zwingend an `functools.partial()` liegt. Wie kommst Du darauf?
mathi
User
Beiträge: 314
Registriert: Dienstag 27. November 2007, 14:30

nun,
ich versuche das skript von 2.7 nach 3.2 zu portieren...
- die 3 Parameter label,newdir und newdate, die an functools übergeben werden, enthalten die gleichen Informationen,
- in der Funktion "label" wurde nichts geändert (ein Bild wird geöffnet, bearbeitet/beschriftet und gespeichert)
- und print() liefert trotzdem nicht das Gleiche -- in python 3.2 werden zusätzliche Werte übergeben
->daher meine Annahme

In der Beschreibung zu functools habe ich aber auch nichts von Änderungen gelesen.

Hier mal die Funktion "label", die mit den 2 zusätzlichen Parametern übergeben wurde...

Code: Alles auswählen

def label(q,newdir,newdate):
    while not q.empty():
        pts = -1
        entry=q.get()

        outname = os.path.join(newdir,entry)
        im = Image.open(entry) 
        if newdate==False:
            exif = jpeg.getExif(entry)
            date = exif.dict()['DateTimeOriginal'][2]
            text = '%s.%s.%s' % (date[8:10], date[5:7], date[:4])
        else:
            text=newdate
        fac = max(im.size) / 3000.0
        newpts = int(fac * 48)
        if pts != newpts:
            pts = newpts
            x = int(fac * 2700)
            y = int(fac * 80)
            font = ImageFont.truetype('arial.ttf', newpts)
        draw = ImageDraw.Draw(im)
        y = im.size[1] - y
        w, h = draw.textsize(text, font=font)
        crop_old = im.crop((x - 1, y - 1, x + w + 1, y + h + 1))
        var_old = sum(ImageStat.Stat(crop_old).var)
        #Mit Schwarz beginnen
        text_col = 0
        #Bis einschließlich Weiß wiederholen
        while text_col <= 0xFFFFFF:
            draw.text((x, y), text, font=font, fill=text_col)
            crop_new = im.crop((x - 1, y - 1,
                                x + w + 1, y + h + 1))
            var_new = sum(ImageStat.Stat(crop_new).var)
            if var_new - var_old > 5000:
                break
            text_col += 0x010101
        else:
            print('Kontrast nicht ausreichend -', end=' ')
            #self.error_flag = True
        if not os.path.isdir(newdir):
            os.mkdir(newdir)
        im.save(outname)
        # Change the date
        jpeg.setExif(exif, outname) 
Daher war ich der Meinung functools ist schuld.
unter 2.7 wird ein "Objekt" übergeben (die Speicheradresse) und unter 3.2 eben nicht, daher der AttributeError oder??
BlackJack

@mathi: Sowohl in Python 2 als auch in Python 3 wird ein Objekt übergeben und keine Speicheradresse. Das was Du mit ``print`` bekommst ist eine Zeichenkettendarstellung des Objekts welche das Objekt selbst liefert. Da kann alles mögliche drin stehen. Das einzige was man an dieser Änderung sehen und mit Sicherheit sagen kann, ist dass sich die `__str__()` oder die `__repr__()`-Methode von diesen Objekten geändert hat, und beide haben ansonsten keinen Einfluss auf das Verhalten von Objekten.

Die Fehlermeldung sagt aus, dass auf einem Objekt vom Typ `NoneType`, also einem `None`-Wert kein Attribut mit dem Namen `dict` existiert. Nun schau doch mal in Deiner `label()`-Funktion wo da auf ein `dict`-Attribut zugegriffen wird. Offensichtlich gibt ``jpeg.getExif(entry)`` unter bestimmten Umständen `None` zurück.

Mit der `q` gehst Du übrigens unsicher um. Wenn die Bedingung der ``while``-Schleife wahr ist, heisst das ja nicht, dass sie das wenn kurz danach `get()` aufgerufen wird, immer noch ist. Da kann die Schleife dann hängen bleiben.
mathi
User
Beiträge: 314
Registriert: Dienstag 27. November 2007, 14:30

vielen Dank für die Hilfe, da hätte ich ja lange suchen können.
Hattest vollkommen recht, es lag an einem nicht kompatiblen modul :-)

Problem gelöst :)
das mit der "while"-Schleife schaue ich mir noch an, danke

Gruß Mathi
Antworten