Closed CyberDefend3r closed 4 years ago
Looks like the problem is that 'modData.encode()' RETURNS an encoded string - it doesn't modify modDate - so you are still passing in a str.
Looks like the problem is that 'modData.encode()' RETURNS an encoded string - it doesn't modify modDate - so you are still passing in a str.
Thank you for pointing this out. Seems that no matter what i do to it it stays a string... Do you have any suggestions?
modDataBytes = modData.encode() should work fine
On Mon, Nov 18, 2019 at 9:05 AM trevormiller6 notifications@github.com wrote:
Looks like the problem is that 'modData.encode()' RETURNS an encoded string - it doesn't modify modDate - so you are still passing in a str.
Thank you for pointing this out. Seems that no matter what i do to it it stays a string... Do you have any suggestions?
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/smarnach/pyexiftool/issues/29?email_source=notifications&email_token=AAHU2T66ONSVUXEHMUOZPW3QULDPDA5CNFSM4JOOK3AKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEELFMAA#issuecomment-555111936, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAHU2T2JSFE5QH4VKKRD2X3QULDPDANCNFSM4JOOK3AA .
--
Chris Wagner
The land embracing Point Lobos was bought for inclusion in the State Park System (a) because the very peculiar physical characteristics of the locality have enabled many people to obtain here personal satisfactions of peculiar kinds which they have valued very highly, and of which the most highly valued are unobtainable elsewhere in like degree if at all, ...
Point Lobos Reserve Master Plan Report - Olmsted Brothers,
November, 1935
modDataBytes = modData.encode() should work fine
Same issue.
def buildEXIFcommand(self):
for filelist in self.dateFile:
date = filelist['date']
for picfile in filelist['pictures']:
modDate = '"' + '-FileCreateDate=' + date + '"'
modDateBytes = modDate.encode()
picfile = exiftool.fsencode(picfile)
self.exifChange(modDateBytes, picfile)
def exifChange(self, modDateBytes, picfile):
with exiftool.ExifTool(self.exifTool) as et:
et.execute(modDateBytes, picfile)
Goodpoint - looking closer - it is failing at the call to 'start' (which is run as part of the 'with' context manager) - so not even looking at your parameters yet.
Looking at the error in subprocess - (which is windows specific alas) - it appears that it (error message not withstanding) it wants a string - not bytes. And as I said before - this is on the start - not your 'execute' command - so that means it must be an issue with your executable. So I would try creating your path WITHOUT .encode() e.g. :
os.path.join(self.curDir, 'exiftool.exe')
lets see what that brings.
Goodpoint - looking closer - it is failing at the call to 'start' (which is run as part of the 'with' context manager) - so not even looking at your parameters yet.
Looking at the error in subprocess - (which is windows specific alas) - it appears that it (error message not withstanding) it wants a string - not bytes. And as I said before - this is on the start - not your 'execute' command - so that means it must be an issue with your executable. So I would try creating your path WITHOUT .encode() e.g. :
os.path.join(self.curDir, 'exiftool.exe')
lets see what that brings.
I get the same traceback
I can confirm all three variables passed to exiftool are bytes objects when printed:
b'C:\\Users\\trevo\\OneDrive\\Desktop\\pics\\exiftool.exe'
b'-FileCreateDate=2018:06:01 00:01:01'
b'C:\\Users\\trevo\\OneDrive\\Desktop\\pics\\2018\\06\\MVIMG_20190719_185858.jpg'
Thanks for the help!
That is my point. Your path to exiftool executable should NOT BE BYTES.
When you use the 'with' stmt - it ends up calling:
self._process = subprocess.Popen( [self.executable, "-stay_open", "True", "-@", "-", "-common_args", "-G", "-n"],
Where self.executable is what you called exifTool's constructor with. Popen takes strings.
However - when you call 'execute(...)' - it is writing to a pipe - and that required bytes - so your date and filename need to be bytes.
That is my point. Your path to exiftool executable should NOT BE BYTES.
When you use the 'with' stmt - it ends up calling:
self._process = subprocess.Popen( [self.executable, "-stay_open", "True", "-@", "-", "-common_args", "-G", "-n"],
Where self.executable is what you called exifTool's constructor with. Popen takes strings.
However - when you call 'execute(...)' - it is writing to a pipe - and that required bytes - so your date and filename need to be bytes.
lol you're right i was being an idiot. I was thinking that was being passed to exiftool so I was doing :
self.exifTool = os.path.join(self.curDir.encode(), 'exiftool.exe'.encode())
AND for some reason:
self.exifTool = exiftool.fsencode(collection.exifTool)
So i changed both of those and ended up getting "OSError: [WinError 10038] An operation was attempted on something that is not a socket" I changed the exiftool.py to be from the commit recommended in that issue and all works now!
Thank you for the help! Much appreciated.
working code:
"""
Used to take pictures seperated into folders based on date like year/month/photo.jpg, and
change the create date of photo to the year and month from the folder names.
The script assumes that exiftool.exe and script are in the same directory. year folders are
in same dir as well.
"""
import os
from glob import glob
import exiftool
class collection:
def __init__(self):
self.dateFile = []
self.fileList = {}
self.paths = glob('**/**')
self.curDir = os.getcwd()
self.exifTool = os.path.join(self.curDir, 'exiftool.exe')
self.overwriteOG = b'-overwrite_original'
def setVariables(self):
for path in self.paths:
globPath = os.path.join(path, '*.*')
picturPath = glob(globPath)
pictures = []
for pic in picturPath:
pictures.append(os.path.join(self.curDir, pic))
date = str.replace(path, '\\', ':') + ':01 00:01:01'
self.fileList = {'date':date, 'pictures':pictures}
self.dateFile.append(self.fileList)
class changeDate:
def __init__(self, collection):
self.dateFile = collection.dateFile
self.exifTool = collection.exifTool
self.overwriteOG = collection.overwriteOG
def buildEXIFcommand(self):
for filelist in self.dateFile:
date = filelist['date']
for picfile in filelist['pictures']:
modAllDate = b'-AllDates=' + date.encode()
modCreateDate = b'-FileCreateDate=' + date.encode()
picfile = exiftool.fsencode(picfile)
self.exifChange(modAllDate, modCreateDate, picfile)
def exifChange(self, modAllDate, modCreateDate, picfile):
with exiftool.ExifTool(self.exifTool) as et:
et.execute(self.overwriteOG, modAllDate, modCreateDate, picfile)
if __name__ == "__main__":
Collection = collection()
print('Collecting Files To change')
Collection.setVariables()
ChangeDate = changeDate(Collection)
print('Changing date on collected files')
ChangeDate.buildEXIFcommand()
print('Completed')
Old thread but this helped me understand how to pass arguments to execute. Can be confusing. Thanks.
I am trying to do something super simple. Well that I thought was simple. I spent like 20 min writing the code and about 2 hours trying to figure out why it doesn't work...
I keep getting a typeError from subprocess called from the exiftool start(). I am sure I am doing something wrong but I cant figure it out. I thought i would post here on the very slim chance this is a bug and not my fault.