ModuleNotFoundError: No module named 'PIL'

Yes, it succeeds.

Hooray.

python3.6 png2jpg.py Dust_Collector.png
Saved as Dust_Collector.png.jpg

Eventually I want to fix it so it outputs Dust_Collector.jpg.

Hmm, Discourse’s email interface has dropped the end of your post. I’ll
snarf it from the forum.

Your code, with some remarks interspersed:

 if len(sys.argv) > 1:
     if os.path.exists(sys.argv[1]):
         im = Image.open(sys.argv[1])

I’d be using a better variable name, eg:

 srcfilename = argv[1]

and then:

 if os.path.exists(srcfilename):
     im = Image.open(srcfilename)

and so on.

 # Backspace 4 spaces  and add .jpg    
 target_name = "sys.argv[1] - 4" + ".jpg"

You’ve enclosed sys.argv[1] - 4 in quotes, which makes it the literal
string "sys.argv[1] - 4". You want:

 target_name = sys.argv[1][:-4] + ".jpg"

You can’t subtract an integer from a string (sys.argv[1] - 4) but if
you want the string except the last 4 characters you can index the
string with a slice [:-4] which means the characters in the string
from the first character up to (and not including) the fourth last
character.

The requires special knowledge of the length of the original extension.
The os.path module has a function to break a filename into its base
and extension called splitext. Using it:

 # up the top
 from os.path import splitext

 # here
 src_base, src_ext = splitext(sys.argv[1])
 target_name = src_base + '.jpg'

os.path.splitext docs

You could also use a format string (“f-string”) to compute target_name
like this:

 target_name = f'{src_base}.jpg'

which most people find more readable.

 else:
     print("Usage: convert2jpg.py <file>")

I usually put this up the top, with an early return:

 if len(argv) < 2:
     print("Usage: convert2jpg.py <file>", file=sys.stderr)
     sys.exit(2)

 src_filename=argv[1]
 ... rest of the program ...

Cheers,
Cameron Simpson cs@cskk.id.au

Thanks, I incorporated your recommendations.
Traceback (most recent call last):
File “test.py”, line 11, in
if len(argv) < 2:
NameError: name ‘argv’ is not defined

import os
import sys
from PIL import Image
 
if len(argv) < 2:
     print("Usage: convert2jpg.py <file>", file=sys.stderr)
     sys.exit(2)
        
srcfilename = argv[1]

if os.path.exists(srcfilename):
     im = Image.open(srcfilename)
      

target_name = sys.argv[1][:-4] + ".jpg"                  

rgb_im = im.convert('RGB')
rgb_im.save(target_name)
      
filename = os.path.basename(target_name)

filename_without_ext = os.path.splitext(filename)[0]
        
print("Saved as " + filename_without_ext )

Ok, I added
from sys import argv


Traceback (most recent call last):
  File "test.py", line 14, in <module>
    srcfilename = argv[1]
IndexError: list index out of range

I kept up at it. I really appreciate all the help.

I am really starting to like python.

if len(argv) < 2:
     print("Usage: convert2jpg.py <file>", file=sys.stderr)
     sys.exit(2)
     
srcfilename = argv[1]     

if os.path.exists(srcfilename):
     im = Image.open(srcfilename)
    
target_name = sys.argv[1][:-4] + ".jpg"                  

rgb_im = im.convert('RGB')
rgb_im.save(target_name)
      
filename = os.path.basename(target_name)

filename_without_ext = os.path.splitext(filename)[0]
        
print("Saved as " + filename_without_ext )

target_name = sys.argv[1][:-4] + “.jpg”

You should be using src_filename here, not sys.argv[1].

rgb_im = im.convert('RGB')
rgb_im.save(target_name)

filename = os.path.basename(target_name)

filename_without_ext = os.path.splitext(filename)[0]

print("Saved as " + filename_without_ext )

But you saved it to target_name

Cheers,
Cameron Simpson cs@cskk.id.au

python3.6 png2jpg.py Dust.png
Saved as Dust.jpg

It is working as I wish, unless you see some big error.

if len(argv) < 2:
     print("Usage: convert2jpg.py <file>", file=sys.stderr)
     sys.exit(2)
     
srcfilename = argv[1]     

if os.path.exists(srcfilename):
     im = Image.open(srcfilename)
    
target_name = sys.argv[1][:-4] + ".jpg"                  

rgb_im = im.convert('RGB')
rgb_im.save(target_name)
      
filename = os.path.basename(target_name)
        
print("Saved as " + filename)

python3.6 png2jpg.py Dust.png
Saved as Dust.jpg

It is working as I wish, unless you see some big error.

There aren’t any big errors, but there are various inconsistencies:

if len(argv) < 2:
    print("Usage: convert2jpg.py <file>", file=sys.stderr)
    sys.exit(2)

srcfilename = argv[1]

if os.path.exists(srcfilename):
    im = Image.open(srcfilename)

target_name = sys.argv[1][:-4] + ".jpg"

You want srcfilename here, not sys.argv[1]. They’re the same thing,
but the point of srcfilename = argv[1] was to give a meaningful name
to this string.

rgb_im = im.convert('RGB')
rgb_im.save(target_name)

filename = os.path.basename(target_name)
print("Saved as " + filename)

Technically, you saved it to target_name, not filename. It just
happens that your test source filename has no additional path
components, so os.path.basename(target_name)==target_name.

Run your script with a longer path to the image, eg:

 python3.6 x.py some/image/in/another/directory/image.png

Your script as written will save to
some/image/in/another/directory/image.jpg but report:

 Saved as image.jpg

Cheers,
Cameron Simpson cs@cskk.id.au

I ran it on a file in a different dir.

test.py /home/andy/dust.png
Traceback (most recent call last):
  File "/home/andy/Python/test.py", line 27, in <module>
    rgb_im = im.convert('RGB')
NameError: name 'im' is not defined
if os.path.exists(srcfilename):
     im = Image.open(srcfilename)
    
target_name = srcfilename[:-4] + ".jpg"                  

rgb_im = im.convert('RGB')
rgb_im.save(target_name)
      
filename = os.path.basename(target_name)
        
print("Saved as " + target_name)

I would guess that the im= line didn’t get run. Was that an existing
file?

That if-statement needs to sidestep the rest of the script if
os.path.exists returns false. This approach is sometimes called “look
before you leap”. A typical Pythonic way to do this is “ask for
forgiveness”: try to load the image and handle the failure, example:

 try:
     im = Image.open(srcfilename)
 except FileNotFoundError as e:
     print("missing file", srcfilename, e, file=sys.stderr)
     sys.exit(1)
 rgb_im = im.convert('RGB')
 ... etc etc ...

Either way, the rgb_im= line needs to only run if you successfully
opened the image file.

Cheers,
Cameron Simpson cs@cskk.id.au

2 Likes