Problem with exiftool in using Python Idle

Started by exif_python, March 17, 2020, 12:42:07 PM

Previous topic - Next topic

exif_python

exiftool is amazing!  (wanted to say that first)

I'm a newbie, so please excuse my grammar.

Anyway, I'm writing a program in Python3.8 which wants to extract exif data from mostly Canon cameras. I succeed with Pillow (from PIL import Image,ExifTags) using a standard piece of code, but it lacks a lot of metadata. Much seems to be tied up in a field called MakerNote, which comes out as coded gibberish.  I install  exiftool and use it on a command line and am impressed  by the amount of data it has. But - I need to call it from my Python program. I use subprocess.call, subprocess.run, subprocess.Popen, e.g. (this is not the code bit I want to use, since it lacks the image file name, but it should run anyway no? and it seems to be the simplest to explain my problem)

import subprocess
import exiftool

subprocess.Popen(['exiftool'],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
stdout, stderr = process.communicate()
print(stdout.decode('utf-8'), stderr)

I  get this error message:

Traceback (most recent call last):
  File "/Users/abo/Documents/test3.py", line 5, in <module>
    subprocess.Popen(['exiftool'],
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/subprocess.py", line 854, in __init__
    self._execute_child(args, executable, preexec_fn, close_fds,
  File "/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/subprocess.py", line 1702, in _execute_child
    raise child_exception_type(errno_num, err_msg, err_filename)
FileNotFoundError: [Errno 2] No such file or directory: 'exiftool'

OK, I search on the web, and it seems (not sure) to be a problem because sys.path does not contain the path which the program needs to see exiftool. I try various fixes (PYTHONPATH etc.), but none as yet have worked. I'm wondering if anyone else has encountered this problem, *specifically with exiftool*, and has a workaround which worked. What must be in sys.path or PYTHONPATH in order for exiftool to be recognised? I'm not even sure about that, so maybe I've just been on a wild goose chase, and there's another problem.

What I would ideally like is instructions so that I can use a simple application of (say) subprocess.run or the like with exiftool. Alternatively, I've tried PyExifTool, but I'm getting the same sort of problem, and I imagine if I can get subprocess.run to work, then I can get PyExifTool to work as well, but perhaps I am in error.

I did try to search this forum, but did not see anything  relevant, so please excuse me if this has already been discussed. Also apologies if this is not appropriate for this forum.

Phil Harvey

QuoteFileNotFoundError: [Errno 2] No such file or directory: 'exiftool'

Did you try "exiftool.exe" instead of "exiftool"?  Where did you put exiftool.exe (you did rename from exiftool(-k).exe, right?)?  Is it in your PATH?  Perhaps try putting the full path for the file in the command.

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

exif_python

Thanks for such a quick reply.  I hadn't tried exiftool.exe, but I just did with

subprocess.Popen(['exiftool.exe'], etc,

and I get the same error message.

I didn't put exiftool anywhere. (Oops?)  i followed these instructions (I'm using 10.14.6):

MacOS Package

1/ Download the ExifTool MacOS Package from the ExifTool home page.
(The file you download should be named "ExifTool-11.91.dmg".)
2/ Install as a normal MacOS package.
(Open the disk image, double-click on the install package, and follow the instructions. See the second item in the Notes section below if you are stopped with an "unidentified developer" message.)
You can now run exiftool by typing "exiftool" in a Terminal window.
3/ If this doesn't work, then it is likely you have an older version of MacOS for which /usr/local/bin isn't in the default PATH. To fix this, add the following line to your ~/.profile settings using a text editor:
export PATH=$PATH:/usr/local/bin

In 2/ you're not given the option of where to install it (there's a Change Install Location, but that's just for the drive, and only one drive is available). I didn't do 3/, because 'exiftool' worked as a command in terminal. In  any case '/usr/local/bin' is (was already) in $PATH. I didn't put exiftool.exe anywhere, nor did I try to rename any file, because I didn't see the instructions which asked me to do either. Maybe that's supposed to be an obvious thing, sorry.  In any case exiftool (the executable unix file) is in usr/local/bin.


Phil Harvey

OK, you're on MacOS.  exiftool.exe is for Windows.

On MacOS, try replacing "exiftool" with "/usr/local/bin/exiftool" to run the script from there.

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

exif_python

And - that worked!  Okay,  well that was simple enough. I tried  really lots and lots  of combinations, but apparently not that...  Thank you so much.  And thanks for exiftool itself, really wonderful program.

For those who come here after, this  is the complete bit of code:

import subprocess
import exiftool

string1='/usr/local/bin/exiftool'
string2=the full file  name written  here (in quotes)
myList = [string1,string2]
process = subprocess.Popen(myList,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
stdout, stderr = process.communicate()
print(stdout.decode('utf-8'), stderr)

stdout then contains all of the metadata which exiftools gets.

Sorry for the bother, it did really have me stuck for  a couple of days, and thanks again.

Liang

#5
Hi I am also a newbie in terms of programming.
I also encountered the same error when I run my script in Anaconda Spyder. Would be appreciate if you could help me out:) Thanks in advance!

Error:
File "/Users/henry/opt/anaconda3/lib/python3.9/subprocess.py", line 1821, in _execute_child
    raise child_exception_type(errno_num, err_msg, err_filename)

FileNotFoundError: [Errno 2] No such file or directory: 'exiftool'


I use Mac version 12.3.1. I followed the instruction from the homepage and when I type "exiftool" in my terminal, there was no error.

I first got the error when I import exiftool in my python script.
ImportError: No module named exiftool
I tried adding the path to the exiftool (/usr/local/bin) executable to the PATH environment variable. Failed, and I change back the original environment variable path.

Also tried the following command in the terminal and got the error
pip install exiftool

ERROR: Could not find a version that satisfies the requirement exifttol (from versions: none)
ERROR: No matching distribution found for exifttol

Then I found people suggested this:

pip install git+https://github.com/smarnach/pyexiftool.git#egg=pyexiftool

Then finally I have no more error for import exiftool, but then I get the error

FileNotFoundError: [Errno 2] No such file or directory: 'exiftool'


This is my python script:

import os
import glob
import exiftool


# Start subprocess with exiftool
et = exiftool.ExifTool()
et.start()


# Returns dictionary with relevant EXIF tags
def get_metadata(fn, et=et):
    tags = ['EXIF:GPSLatitude', 'EXIF:GPSLongitude', 'EXIF:GPSLatitudeRef', 'EXIF:GPSLongitudeRef', \
            'EXIF:GPSAltitude', 'EXIF:GPSAltitudeRef', 'XMP:AbsoluteAltitude', 'XMP:RelativeAltitude']
    metadata = et.get_tags(tags, fn)
    # Convert to positive east longitude
    if metadata['EXIF:GPSLongitudeRef'] == "W":
        metadata['EXIF:GPSLongitude'] *= -1
    if metadata['EXIF:GPSLatitudeRef'] == "S":
        metadata['EXIF:GPSLatitude'] *= -1
    print(metadata)
    return metadata


def update_gps_altitude(fn, home_elev):

    metadata = get_metadata(fn)
    relAlt = float(metadata['XMP:RelativeAltitude'])
    home_elev = float(home_elev)
    print(relAlt)
    adjAlt = home_elev + relAlt

    # Update metadata
    etArg = ["-GPSAltitude=" + str(adjAlt), ]
    etArg.append("-AbsoluteAltitude=" + str(adjAlt))

    # Set altitude reference
    # 1 is 'Below Sea Level'; 0 is 'Above Sea Level'
    if adjAlt >= 0.0:
        etArg.append("-GPSAltitudeRef=0")
    else:
        etArg.append("-GPSAltitudeRef=1")

    # Since we're modifying our own copy of originl, we don't need the default exiftool _original copy
    etArg.append("-overwrite_original")
    print(etArg)

    # pyexiftool execution requires binary string
    etArg_b = [str.encode(a) for a in etArg]
    f_b = str.encode(fn)
    etArg_b.append(f_b)
    et.execute(*etArg_b)

    # Check updated
    metadata = get_metadata(fn)


def main(img_dir, home_elev):
    image_dir = img_dir
    home_elev = str(home_elev)

    fn_list_orig = sorted(glob.glob(os.path.join(image_dir, '*.JPG')))

    for fn in fn_list_orig:
        update_gps_altitude(fn, home_elev)

    et.terminate()

#####################
###### Altitude Adjust
####################

#Required input is the directory of the images to be adjusted
#NOTE: The images are updated and saved in the image, not in a copy

img_dir = '/Volumes/MasterLiang/Testing script/'
home_elev = 0

if __name__ == "__main__":
    main(img_dir, home_elev)

StarGeek

I'm not very knowledgeable about Python, but yes, you do have to make sure that PyExifTool is installed for import exiftool to work.

But since you're still getting an file not found error when it tries to run exiftool, it seems like that exiftool isn't part of the path that Python can access.

Maybe change line 70 in exiftool.py so it includes the full path to exiftool.  Assuming that exiftool is in /usr/local/bin, instead of
executable = "exiftool"
it would be
executable = "/usr/local/bin/exiftool"
"It didn't work" isn't helpful. What was the exact command used and the output.
Read FAQ #3 and use that cmd
Please use the Code button for exiftool output

Please include your OS/Exiftool version/filetype