timpanists
timpanists

Reputation: 27

Errno 20: Not a directory when saving into zip file

When I try to save a pyplot figure as a jpg, I keep getting a directory error saying that the given file name is not a directory. I am working in Colab. I have a numpy array called z_img and have opened a zip file.

import matplotlib.pyplot as plt
from zipfile import ZipFile

zipObj = ZipFile('slices.zip', 'w') # opening zip file
plt.imshow(z_img, cmap='binary')

The plotting works fine. I did a test of saving the image into Colab's regular memory like so:

plt.savefig(str(ii)+'um_slice.jpg')

And this works perfectly, except I am intending to use this code in a for loop. ii is an index to differentiate between each image, and several hundred images would be created so I want them going in the zipfile. Now when I try adding the path to the zipfile:

plt.savefig('/content/slices.zip/'+str(ii)+'um_slice.jpg')

I get: NotADirectoryError: [Errno 20] Not a directory: '/content/slices.zip/150500um_slice.jpg'

I assume it's because the {}.jpg string is a filename, and not a directory per se. But I am quite new to Python, and don't know how to get the plot into the zip file. That's all I want. Would love any advice!

Upvotes: 0

Views: 771

Answers (2)

tdelaney
tdelaney

Reputation: 77387

From the docs, matplotlib.pyplot.savefig accepts a binary file-like object. ZipFile.open creates binary file like objects. These two have to get todgether!

with zipobj.open(str(ii)+'um_slice.jpg', 'w') as fp: 
    plt.savefig(fp)

Upvotes: 0

Marcus Müller
Marcus Müller

Reputation: 36462

First off, for anything that's not photographic content (ie. nice and soft), JPEG is the wrong format. You'll have a better time using a different file format. PNG is nice for pixels, SVG for vector graphics (in case you embed this in a website later!), PDF for vector, too.

The error message is quite on point: you cannot just save to a zip file as if it was a directory.

Multiple ways around:

  • use the tempfile module's mkdtemp to make a temporary directory, save into that, and zip the result
  • save not into a filename, but into a buffer (BytesIO I guess) and append that to the compressed stream (I'm not too familiar with ZipFile)
  • use PDF as output and simply generate a multipage PDF; it's not hard, and probably much nicer in the long term. You can still convert that vector graphic result to PNG (or any other pixel format9 as desired, but for the time being, it's space efficient, arbitrarily scaleable and keeps all your pages in one place. It's easy to import selected pages into LaTeX (matter of fact, \includegraphics does it directly) or into websites (pdf.js).

Upvotes: 1

Related Questions