Search code examples
pythondjangopython-3.xpython-imaging-library

Python3 Django1.9 PIL Issue involving Saving Image File with io.BytesIO - Works in Terminal but not in the Server


Python : 3.4.3
Django : 1.9.7
Exception Type: TypeError
Exception Value: descriptor 'fileno' of '_io._IOBase' object needs an argument
Exception Location: /usr/lib/python3/dist-packages/PIL/ImageFile.py in _save, line 454

This is the code I have tested in the terminal -

 import urllib.request
 from PIL import Image
 from io import BytesIO

 url = 'http://s.inyourpocket.com/gallery/108367.jpg'
 i = Image.open(BytesIO(urllib.request.urlopen(url).read()))
 img_file = BytesIO()
 i.save(img_file, 'JPEG')

The code works perfectly well in the terminal but as soon as it's tested on the Django server it gives me these errors -

File "PATH/utils.py", line 124, in pil_to_django
  image.save(img_file, 'JPEG')
File "/usr/lib/python3/dist-packages/PIL/Image.py", line 1468, in save
  save_handler(self, fp, filename)
File "/usr/lib/python3/dist-packages/PIL/JpegImagePlugin.py", line 579, in _save
  ImageFile._save(im, fp, [("jpeg", (0,0)+im.size, 0, rawmode)], bufsize)
File "/usr/lib/python3/dist-packages/PIL/ImageFile.py", line 454, in _save
  fh = fp.fileno()
TypeError: descriptor 'fileno' of '_io._IOBase' object needs an argument

The code running in the server is in utils.py which is called from views.py -

# utils.py
def pil_to_django(image, format="JPEG"):
    img_file = io.BytesIO
    image.save(img_file, 'JPEG')
    return ContentFile(img_file.getvalue())


# views.py
pil_image = Image.open(BytesIO(urllib.request.urlopen(url).read()))
django_file = pil_to_django(pil_image)

Solution

  • You forgot to instantiate BytesIO class. Change img_file = io.BytesIO to img_file = io.BytesIO()