accessing 'Iptc.Application2.DateCreated' causes TypeError: object of type 'datetime.date' has no len()

Asked by fenris

I have the following code below:

#----------------------------------
import pyexiv2

def update_image_iptc(path, **iptc):
    """
    This takes an image and updates the iptc information based on the passed parameters
    """

    if not os.path.exists(path):
        raise Exception, '%s does not exist!' % path

    image = pyexiv2.Image(path)
    image.readMetadata()

    if 'exifDateTime' in iptc:
        #storedDate = image['Iptc.Application2.DateCreated']
        image['Iptc.Application2.DateCreated'] = iptc['exifDateTime'].isoformat() #assign a datetime object

    if 'photographer' in iptc:
        image['Iptc.Application2.Byline'] = iptc['photographer']
        image['Iptc.Application2.Writer'] = iptc['photographer']

    if 'copyright' in iptc:
        image['Iptc.Application2.Copyright'] = iptc['copyright']

    image.writeMetadata()
#---------

If I run it as is I get the following error:

Traceback (most recent call last):
  File "./camera_copy2.py", line 511, in <module>
    status = main()
  File "./camera_copy2.py", line 488, in main
    copyright=configParams['copyright'])
  File "./camera_copy2.py", line 373, in update_image_iptc
    image['Iptc.Application2.DateCreated'] = iptc['exifDateTime'].isoformat()
  File "/usr/lib/pymodules/python2.6/pyexiv2.py", line 648, in __setitem__
    for i in xrange(max(len(oldValues), len(newValues))):
TypeError: object of type 'datetime.date' has no len()

If I uncomment the line:
#storedDate = image['Iptc.Application2.DateCreated']

It works fine. I would like to know what is going on? Is this how I am supposed to set the IPTC date created field? Do I have to access the tag first before I can write a value to it?

Cheers,
Troy

Question information

Language:
English Edit question
Status:
Solved
For:
pyexiv2 Edit question
Assignee:
No assignee Edit question
Solved by:
fenris
Solved:
Last query:
Last reply:
Revision history for this message
Olivier Tilloy (osomon) said :
#1

Hi Troy,

You're hitting a known bug that was fixed in pyexiv2 0.2 (bug #343403).
What happens if you try to set the value of image['Iptc.Application2.DateCreated'] to a list (containing only one value)? I.e.:

    image['Iptc.Application2.DateCreated'] = [iptc['exifDateTime'].isoformat()]

The handling of IPTC values in 0.1.x is buggy. In 0.2, values of IPTC tags are expected to always be lists for consistency.

I hope this helps.

Revision history for this message
fenris (troy-williams) said :
#2

Hi Olivier,

Thank you very much for the response!

Sorry for my tardy reply.

I set the line so that it passes a list and this is what I get:

    image['Iptc.Application2.DateCreated'] =
[iptc['exifDateTime'].isoformat()]
   File "/usr/lib/pymodules/python2.6/pyexiv2.py", line 648, in __setitem__
     for i in xrange(max(len(oldValues), len(newValues))):
TypeError: object of type 'datetime.date' has no len()

This is the line in my python script changed based on your recommendation:

image['Iptc.Application2.DateCreated'] = [iptc['exifDateTime'].isoformat()]

I am using ubuntu karmic (9.10) and the version of pyexiv2 is
0.1.3-3build1. Is there a ppa where I can get the 0.2 line? I noticed
there is a repo here
https://launchpad.net/~pyexiv2-developers/+archive/ppa but it is for
lucid. Should I wait for lucid or can I use the ppa currently to upgrade
and test it out?

Thanks,
Troy

On 10-04-11 03:02 PM, Olivier Tilloy wrote:
> Your question #107082 on pyexiv2 changed:
> https://answers.edge.launchpad.net/pyexiv2/+question/107082
>
> Status: Open => Answered
>
> Olivier Tilloy proposed the following answer:
> Hi Troy,
>
> You're hitting a known bug that was fixed in pyexiv2 0.2 (bug #343403).
> What happens if you try to set the value of image['Iptc.Application2.DateCreated'] to a list (containing only one value)? I.e.:
>
> image['Iptc.Application2.DateCreated'] =
> [iptc['exifDateTime'].isoformat()]
>
> The handling of IPTC values in 0.1.x is buggy. In 0.2, values of IPTC
> tags are expected to always be lists for consistency.
>
> I hope this helps.
>
>

Revision history for this message
Olivier Tilloy (osomon) said :
#3

pyexiv2 0.2 in the PPA is indeed only available for Lucid, because it needs to be compiled against libexiv2 0.19, which is not available in Karmic. If you can wait until Lucid is released then I would advise you to go for pyexiv2 0.2, it has a lot of bug fixes and improvements over 0.1, including a more flexible API and better documentation.

I had a look at the code of 0.1, and unfortunately I can't think of an easy workaround to this issue without patching pyexiv2's code.

Revision history for this message
fenris (troy-williams) said :
#4

Olivier,

I can wait till lucid. I'll upgrade the code then. I am only writing a
small application that copies images from a camera and renames them
based on the exif date they were taken. In addition it also sets the
IPTC tag for photographer and a few other things automatically.

Cheers and thanks,
Troy

On 10-04-14 09:49 AM, Olivier Tilloy wrote:
> Your question #107082 on pyexiv2 changed:
> https://answers.edge.launchpad.net/pyexiv2/+question/107082
>
> Status: Open => Answered
>
> Olivier Tilloy proposed the following answer:
> pyexiv2 0.2 in the PPA is indeed only available for Lucid, because it
> needs to be compiled against libexiv2 0.19, which is not available in
> Karmic. If you can wait until Lucid is released then I would advise you
> to go for pyexiv2 0.2, it has a lot of bug fixes and improvements over
> 0.1, including a more flexible API and better documentation.
>
> I had a look at the code of 0.1, and unfortunately I can't think of an
> easy workaround to this issue without patching pyexiv2's code.
>
>

Revision history for this message
Olivier Tilloy (osomon) said :
#5

Hi Troy,

As a temporary fall-back solution, you may want to consider invoking exiv2 from the command line, all the simple manipulations you are mentioning are easy to perform.

Another possible solution if you don't have distribution constraints (i.e. if you're only running this script locally on your machine) is to install locally pyexiv2 0.2 from source. Check out the documentation at http://tilloy.net/dev/pyexiv2/developers.html.
Note that you will have to compile libexiv2 0.19 from source.

The last alternative is to patch pyexiv2 0.1's code. Following is a simple patch that should do the trick. Disclaimer, though: I didn't test it, I can't guarantee it won't break anything:

=== modified file 'src/pyexiv2.py'
--- src/pyexiv2.py 2009-03-14 21:43:49 +0000
+++ src/pyexiv2.py 2010-04-15 08:41:17 +0000
@@ -622,6 +622,8 @@
     # The tag is not cached yet
     try:
      oldValues = self.__getitem__(key)
+ if oldValues.__class__ is not tuple:
+ oldValues = (oldValues,)
     except KeyError:
      # The tag is not set
      oldValues = ()

I hope this helps!

Revision history for this message
Olivier Tilloy (osomon) said :
#6

Damn, launchpad didn't respect the formatting of the patch. You will find it at http://tilloy.net/oldValues-len.patch.

Revision history for this message
fenris (troy-williams) said :
#7

Olivier,

The patch did the trick, it doesn't error anymore (well based on my limited testing anyway).

I must say that is the first time I have applied a patch - talk about simplicity. I love Linux more and more every day.

Cheers and thanks for a great script,
Troy