Skip to main content

Python interface to libexiv2

Project description

python-exiv2 is a low level interface (or binding) to the exiv2 C++ library. It is built using SWIG to automatically generate the interface code. The intention is to give direct access to all of the top-level classes in libexiv2, but with additional “Pythonic” helpers where necessary.

Introduction

There are several other ways to access libexiv2 from within Python. The first one I used was pyexiv2 (old). After its development ceased I moved on to using gexiv2 and PyGObject. This works well, providing a Metadata object with high level functions such as set_tag_string and set_tag_multiple to get and set metadata values.

A more recent development is pyexiv2 (new). This new project is potentially very useful, providing a simple interface with functions to read and modify metadata using Python dict parameters.

For more complicated metadata operations I think a lower level interface is required, which is where this project comes in.

This project is at an early stage of development. I’ve managed to get it to build and run with libexiv2 v0.26 and v0.27.4 on Linux, and v0.27.4 on Windows. Here is an example of what it can do:

Python 3.6.12 (default, Dec 02 2020, 09:44:23) [GCC] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import exiv2
>>> image = exiv2.ImageFactory.open('IMG_0211.JPG')
>>> image.readMetadata()
>>> data = image.exifData()
>>> data['Exif.Image.Artist']._print()
'Jim Easterbrook'
>>>

There’s still a lot to be done:

  • Package for PyPI.

  • Create “wheels” for different Python versions.

  • More example files.

Documentation

The libexiv2 library is well documented for C++ users, in Doxygen format. Recent versions of SWIG can convert this documentation to pydoc format in the Python interface:

pydoc3 exiv2.Image.exifData

Help on method_descriptor in exiv2.Image:

exiv2.Image.exifData = exifData(...)
    Returns an ExifData instance containing currently buffered
        Exif data.

    The contained Exif data may have been read from the image by
    a previous call to readMetadata() or added directly. The Exif
    data in the returned instance will be written to the image when
    writeMetadata() is called.

    :rtype: :py:class:`ExifData`
    :return: modifiable ExifData instance containing Exif values

Assignment

libexiv2 stores metadata values in a generalised container whose type can be set by the type of a value assigned to it, for example:

exifData["Exif.Image.SamplesPerPixel"] = uint16_t(162);

This forces the Exif.Image.SamplesPerPixel value to be an unsigned short. Python doesn’t have such specific integer types, so if you want to set the type you need to create an exiv2 value of the appropriate type and assign that:

exifData["Exif.Image.SamplesPerPixel"] = exiv2.UShortValue(162)

This allows you to set the value to any type, just like in C++, but the Python interface warns you if you set a type that isn’t the default for that tag. Otherwise you can set the value to any Python object and let libexiv2 convert the string representation of that object to the appropriate type:

exifData["Exif.Image.SamplesPerPixel"] = 162

Iterators

Several libexiv2 classes use C++ iterators to expose private data, for example the ExifData class has a private member of std::list<Exifdatum> type. The classes have public begin and end methods that return std::list iterators. In C++ you can dereference one of these iterators to access the Exifdatum object, but Python doesn’t have a dereference operator.

This Python interface converts the std::list iterator to a Python object that has a curr method to return the list value. It is quite easy to use:

Python 3.6.12 (default, Dec 02 2020, 09:44:23) [GCC] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import exiv2
>>> image = exiv2.ImageFactory.open('IMG_0211.JPG')
>>> image.readMetadata()
>>> data = image.exifData()
>>> b = data.begin()
>>> b.curr().key()
'Exif.Image.ProcessingSoftware'
>>>

The Python iterators also have a next method that increments the iterator as well as returning the list value. This can be used to iterate over the data in a very C++ like style:

>>> data = image.exifData()
>>> b = data.begin()
>>> e = data.end()
>>> while b != e:
...     b.next().key()
...
'Exif.Image.ProcessingSoftware'
'Exif.Image.ImageDescription'
[skip 227 lines]
'Exif.Thumbnail.JPEGInterchangeFormat'
'Exif.Thumbnail.JPEGInterchangeFormatLength'
>>>

You can also iterate in a more Pythonic style:

>>> data = image.exifData()
>>> for item in data:
...     item.key()
...
'Exif.Image.ProcessingSoftware'
'Exif.Image.ImageDescription'
[skip 227 lines]
'Exif.Thumbnail.JPEGInterchangeFormat'
'Exif.Thumbnail.JPEGInterchangeFormatLength'
>>>

I think this is much better.

Warning: segmentation faults

It is easy to crash python-exiv2 if you delete objects which contain data that another object is pointing to. For example, deleting an Image after extracting its metadata can cause a segfault when the metadata is accessed. Ideally the Python interface to libexiv2 would use Python objects’ reference counts to ensure this doesn’t happen, preventing the deletion of the Image object until all references to it have been deleted. Unfortunately I haven’t found a sensible way to do this in the Python interface, so some care is needed when using it.

Error handling

libexiv2 has a multilevel warning system a bit like Python’s standard logger. The Python interface redirects all Exiv2 messages to Python logging with an appropriate log level.

Installation

Eventually you will be able to install python-exiv2 with a simple pip3 install python-exiv2 command on most computers. Until then the installation process includes a compilation step. This requires the “development headers” of Python3, and an appropriate compiler & linker (GNU C++ on Linux, Visual C++ on Windows).

Once you’ve installed the necessary compiler you can run the pip3 command (or pip if you don’t have Python 2 on your computer), for example:

sudo pip3 install python-exiv2

Leave out the sudo if you’re on Windows. On other operating systems you can install for a single user with the --user option:

sudo pip3 install python-exiv2

Since version 0.2.0 the python-exiv2 package on PyPI includes a copy of the libexiv2 library and its header files, so you don’t need to install your own. If a system installed version of libexiv2 is available it will be used instead, as it’s more likely to be compatible with your operating system.

Building python-exiv2

If you want customise your installation of python-exiv2 you can build it yourself. Download and unpack a source archive from PyPI or GitHub, then switch to the python-exiv2 directory. The setup.py script used to install python-exiv2 will use the libexiv2 installed by your operating system if it can find it. This usually requires the “development headers” package to be installed. In this case you just need to build python-exiv2 and install it as follows:

python3 setup.py bdist_wheel
sudo pip3 install dist/python_exiv2-0.2.0-cp36-cp36m-linux_x86_64.whl

(The name of the wheel file will depend on the python-exiv2 version, your Python version, and the system architecture.)

If you want to use your own downloaded copy of libexiv2 then a few more steps are required. First you need to copy some files using the copy_libexiv2.py script. This has two parameters: the exiv2 directory and the exiv2 version. For example:

python3 utils/copy_libexiv2.py ../exiv2-0.27.4-Linux64 0.27.4

This copies the exiv2 header files and runtime library to the directory libexiv2_0.27.4/linux/. Now you can run setup.py as before. Note that setup.py will still use the system installed version of libexiv2 if it can find it. Uninstalling the “development headers” package will prevent this.

When you try to import exiv2 into Python it’s possible you might get an error like OSError: /lib64/libm.so.6: version `GLIBC_2.29' not found (required by /usr/lib64/python3.6/site-packages/exiv2/libexiv2.so.0.27.4). This happens if the downloaded copy of libexiv2 was built for a newer version of the GNU C library than is installed on your computer. In this case the only option is to build libexiv2 from source.

Download the exiv2 source archive, then follow the build instructions in README.md, but make sure you install to a local directory rather than /usr/local:

$ mkdir build && cd build
$ cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../local_install
$ cmake --build .
$ make install

Then, back in your python-exiv2 directory, copy sources from the newly created local directory:

python3 utils/copy_libexiv2.py ../exiv2-0.27.4-Source/local_install 0.27.4

Then run setup.py as before.

Problems?

I think it’s a bit early in the project to be using the “issues” page. Please email jim@jim-easterbrook.me.uk if you find any problems (or solutions!).

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

python-exiv2-0.2.2.zip (5.2 MB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

python_exiv2-0.2.2-cp39-cp39-win_amd64.whl (1.8 MB view details)

Uploaded CPython 3.9Windows x86-64

python_exiv2-0.2.2-cp38-cp38-win_amd64.whl (1.8 MB view details)

Uploaded CPython 3.8Windows x86-64

python_exiv2-0.2.2-cp37-cp37m-win_amd64.whl (1.7 MB view details)

Uploaded CPython 3.7mWindows x86-64

python_exiv2-0.2.2-cp36-cp36m-win_amd64.whl (1.7 MB view details)

Uploaded CPython 3.6mWindows x86-64

python_exiv2-0.2.2-cp35-cp35m-win_amd64.whl (1.7 MB view details)

Uploaded CPython 3.5mWindows x86-64

File details

Details for the file python-exiv2-0.2.2.zip.

File metadata

  • Download URL: python-exiv2-0.2.2.zip
  • Upload date:
  • Size: 5.2 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.15.0 pkginfo/1.5.0.1 requests/2.24.0 setuptools/40.5.0 requests-toolbelt/0.9.1 tqdm/4.45.0 CPython/3.6.12

File hashes

Hashes for python-exiv2-0.2.2.zip
Algorithm Hash digest
SHA256 96258939b62fa9f55ee2d8cb0f6a7d935e694d05d74663a07c3634797296139a
MD5 d96fe2400a3d5c55854ecc6e27b7c425
BLAKE2b-256 7637d71969d6b7047f5ffa29887229bb9a87de3140a33db171edb126b66e9498

See more details on using hashes here.

File details

Details for the file python_exiv2-0.2.2-cp39-cp39-win_amd64.whl.

File metadata

  • Download URL: python_exiv2-0.2.2-cp39-cp39-win_amd64.whl
  • Upload date:
  • Size: 1.8 MB
  • Tags: CPython 3.9, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.15.0 pkginfo/1.5.0.1 requests/2.24.0 setuptools/40.5.0 requests-toolbelt/0.9.1 tqdm/4.45.0 CPython/3.6.12

File hashes

Hashes for python_exiv2-0.2.2-cp39-cp39-win_amd64.whl
Algorithm Hash digest
SHA256 5da1d2dc25bfdffd743cd59df18cecf5db218551e60ab11a19eaf294c6a8dfbf
MD5 5667e0a2b7f998d55f29015a847b9e42
BLAKE2b-256 e444b06be02f3fe0dcd35632ae63942d8169c150409b74750734c2027f706f9b

See more details on using hashes here.

File details

Details for the file python_exiv2-0.2.2-cp38-cp38-win_amd64.whl.

File metadata

  • Download URL: python_exiv2-0.2.2-cp38-cp38-win_amd64.whl
  • Upload date:
  • Size: 1.8 MB
  • Tags: CPython 3.8, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.15.0 pkginfo/1.5.0.1 requests/2.24.0 setuptools/40.5.0 requests-toolbelt/0.9.1 tqdm/4.45.0 CPython/3.6.12

File hashes

Hashes for python_exiv2-0.2.2-cp38-cp38-win_amd64.whl
Algorithm Hash digest
SHA256 38aae992fc6cb04b0ae254f7677eb505cd74fd1ece1cd4f146a52b4db5c3f254
MD5 03b22442ee364326ea2310fed8511825
BLAKE2b-256 a3ed88d84667a150210b8780f6403e755648323ddf4ec2969c69f480365aaeb3

See more details on using hashes here.

File details

Details for the file python_exiv2-0.2.2-cp37-cp37m-win_amd64.whl.

File metadata

  • Download URL: python_exiv2-0.2.2-cp37-cp37m-win_amd64.whl
  • Upload date:
  • Size: 1.7 MB
  • Tags: CPython 3.7m, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.15.0 pkginfo/1.5.0.1 requests/2.24.0 setuptools/40.5.0 requests-toolbelt/0.9.1 tqdm/4.45.0 CPython/3.6.12

File hashes

Hashes for python_exiv2-0.2.2-cp37-cp37m-win_amd64.whl
Algorithm Hash digest
SHA256 bf874debc79e38eb4fbfec131f2efa70adab2d1ccea077cac894ce6d499c4080
MD5 84306c17bd687b03376cbcf7db937e4a
BLAKE2b-256 95aa8ed5fbd3ee83cf867fbba81424c180cd20ba9063bbcc666efaf42e1311e8

See more details on using hashes here.

File details

Details for the file python_exiv2-0.2.2-cp36-cp36m-win_amd64.whl.

File metadata

  • Download URL: python_exiv2-0.2.2-cp36-cp36m-win_amd64.whl
  • Upload date:
  • Size: 1.7 MB
  • Tags: CPython 3.6m, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.15.0 pkginfo/1.5.0.1 requests/2.24.0 setuptools/40.5.0 requests-toolbelt/0.9.1 tqdm/4.45.0 CPython/3.6.12

File hashes

Hashes for python_exiv2-0.2.2-cp36-cp36m-win_amd64.whl
Algorithm Hash digest
SHA256 cc86a05a94842eb25fcbc78f7b291f885e04e29ccbd4bc1eaa000c5bce78443f
MD5 58208295a22f1ac15d5897d031b4fd9c
BLAKE2b-256 a9fb173034ef7a2c6e328058b12680db48e94a8281fd7bbec95d8078702bd0f3

See more details on using hashes here.

File details

Details for the file python_exiv2-0.2.2-cp35-cp35m-win_amd64.whl.

File metadata

  • Download URL: python_exiv2-0.2.2-cp35-cp35m-win_amd64.whl
  • Upload date:
  • Size: 1.7 MB
  • Tags: CPython 3.5m, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/1.15.0 pkginfo/1.5.0.1 requests/2.24.0 setuptools/40.5.0 requests-toolbelt/0.9.1 tqdm/4.45.0 CPython/3.6.12

File hashes

Hashes for python_exiv2-0.2.2-cp35-cp35m-win_amd64.whl
Algorithm Hash digest
SHA256 6531d0c460eb202b4c89f11f90e455b91af621094cf2e538cc6b5d5d37392136
MD5 37f5f70a56b4cf288688ecd4b7673751
BLAKE2b-256 ea3daed12377d0710219df02b965c89e5a214d43d01d408ed7b9aa04bb9d1c06

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page