0

I currently have a Python function that reads in image files and outputs the image, and then deletes the temporary files when I'm done using them with the os.remove function.

When I try to use the os.remove function, however, I get a permission denied error stating that the file is still in use. I've tried following what this answer suggests, but it hasn't quite worked (or I haven't implemented it correctly).

Here's the code in question:

def image_from_url(url):
    try:
        f = urllib.request.urlopen(url)
        _, fname = tempfile.mkstemp()

        with open(fname, 'wb') as ff:
            ff.write(f.read())

        img = imread(fname)
        os.remove(fname)

        return img
    except urllib.error.URLError as e:
        print('URL Error: ', e.reason, url)
    except urllib.error.HTTPError as e:
        print('HTTP Error: ', e.code, url)

I've tried putting the img = imread(fname) line within the with open block but that hasn't worked.

Does anybody have an idea on what the problem may be? Thank you.

EDIT

More specifically, this function is being called by another script:

# Sample a minibatch and show the images and captions
batch_size = 3

captions, features, urls = coco_minibatch(data, batch_size=batch_size)
for i, (caption, url) in enumerate(zip(captions, urls)):
    plt.imshow(image_from_url(url))
    plt.axis('off')
    caption_str = decode_captions(caption, data['idx_to_word'])
    plt.title(caption_str)
    plt.show()

You can see that the image_from_url function is being called in the first line within the for loop.

The error traceback is as follows:

---------------------------------------------------------------------------
PermissionError                           Traceback (most recent call last)
<ipython-input-5-fe0df6739091> in <module>
      4 captions, features, urls = sample_coco_minibatch(data, batch_size=batch_size)
      5 for i, (caption, url) in enumerate(zip(captions, urls)):
----> 6     plt.imshow(image_from_url(url))
      7     plt.axis('off')
      8     caption_str = decode_captions(caption, data['idx_to_word'])

~\directory\image_utils.py in image_from_url(url)
     73 
     74         img = imread(fname)
---> 75         os.remove(fname)
     76 
     77         return img

PermissionError: [WinError 32] The process cannot access the file because it is being used by another process: 'C:\\Users\\JohnDoe\\AppData\\Local\\Temp\\tmp_lg3agzf'
Sean
  • 2,890
  • 8
  • 36
  • 78

1 Answers1

0
_, fname = tempfile.mkstemp()

will open the newly created temporary file and return the opened file and the name as a tuple. The obvious wrong solution is to do

    temporary_file, fname = tempfile.mkstemp()

    with temporary_file as ff:
        ff.write(f.read())
        img = imread(fname)

    os.remove(fname)

The correct solution is to not use mkstemp but use NamedTemporaryFile instead:

with tempfile.NamedTemporaryFile() as ff:
    ff.write(f.read())
    img = imread(ff.name)

And you do not need to worry about deletion.