user2324278
user2324278

Reputation: 71

Images don't open using Image.open(fnames) and code have " 'list' object has no attribute 'read' " error

I have some subfolders(s1,s2,s3,...). I want to open images in the subfolders in the "Image" folder in path:
"E:/Image/" and show them. But images can not be opened.

import os
from PIL import Image
root = "E:/Image/" 
path = os.path.join(root,"")
for r in os.walk(path):
     for file in r:
        fnames = glob.glob(f'{root}{r}/{file}')
        img1 = Image.open(fnames)
        img1.show()  

My code have this error:

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
~\Anaconda3\lib\site-packages\PIL\Image.py in open(fp, mode)
   2546     try:
-> 2547         fp.seek(0)
   2548     except (AttributeError, io.UnsupportedOperation):

AttributeError: 'list' object has no attribute 'seek'

During handling of the above exception, another exception occurred:

AttributeError                            Traceback (most recent call last)
<ipython-input-5-e9dafc96965e> in <module>()
      9         fnames = glob.glob(f'{root}{r}/{file}')
     10 
---> 11         img1 = Image.open(fnames)
     12        
     13         img1.show()

~\Anaconda3\lib\site-packages\PIL\Image.py in open(fp, mode)
   2547         fp.seek(0)
   2548     except (AttributeError, io.UnsupportedOperation):
-> 2549         fp = io.BytesIO(fp.read())
   2550         exclusive_fp = True
   2551 

AttributeError: 'list' object has no attribute 'read'

Upvotes: 2

Views: 2467

Answers (1)

Francesco Montesano
Francesco Montesano

Reputation: 8658

You get the exception because you pass a list to instead of a file name to Image.open.

However the main issues that I see are related to the wrong use of os.walk and glob.glob. I suggest to carefully read the documentation before using a functionality that you don't know.

A clarification:

  • os.walk doesn't return the name of the files in path but, recursively, a directory (dirpath), the list of subdirectories (dirnames) and the list of the files in the directory (filenames). You can get all the file names simply doing os.path.join(dirpath, name) for each name in in filenames.
  • glob.glob returns a list of files matching the given wildcards. From your code, I imagine that you expect that f'{root}{r}/{file}' is the name of a file on the system, so there is no need to complicate your life using glob.glob

A a couple of notes:

  • since your root already has a trailing /, the call to os.path.join(root,"") does nothing;
  • if you want to create file paths programmatically, do not add path separators by hand, but try to use os.path.join (or if necessary os.sep) as much as possible (it helps to maintain cross-system compatibility). As example instead of doing

    root = "E:/Image/" 
    r = 'folder'
    file = 'test.txt'
    fname = f'{root}{r}/{file}'
    

    use

    root = "E:/Image" 
    r = 'folder'
    file = 'test.txt'
    fname = os.path.join(root, r, file)
    

The code

And now the "correct" code. Since I don't know your directory structure, user case and such, the code might now work as you want, but I hope that you can adapt it to your needs.

import os
from PIL import Image

root = "E:/Image/" 
for dirpath, _, filenames in os.walk(path):
    # we don't care about ``dirnames``
    for name in filenames:
        fname = op.path.join(dirpath, name)
        img1 = Image.open(fname)
        img1.show()  

Upvotes: 3

Related Questions