Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check if an object is a file in Python 2 and 3

Is there a Python 2/3-compatible way of checking whether an object is a file?

I need to check if an object filehandler is actually a file object. This code needs to run in both Python 2 and 3. In Python 2 I could do

isinstance(filehandler, file)

However file is not part of Python 3, so this code raises a NameError when run with Python 3.

According to this answer, in Python 3 io.IOBase should be used to check if an object is a file, but Python 2's file doesn't subclass io.IOBase, so isinstance(filehandler, io.IOBase) won't work.

I thought about doing isinstance(filehandler, (io.IOBase, file)), but that still gives a NameError when I run it with Python 3.

Is there a way to do this that is compatible with both Python 2.7 and 3?

like image 539
jpyams Avatar asked Oct 28 '22 22:10

jpyams


2 Answers

I found that the most common way of doing this is to check hasattr in Python 3. So, I added a check that will check the version of Python, and depending on that, it will execute the right function.

import sys

def isFile(f):
    return isinstance(f,file) if sys.version_info[0] == 2 else hasattr(f, 'read')        

f = open("post.php","r")
print(isFile(f))
print(isFile(10))

Alternatively, you can use a lambda, but I find it less readable.

isFile = lambda f:isinstance(f,file) if sys.version_info[0] == 2 else hasattr(f, 'read')   
like image 134
Neil Avatar answered Nov 13 '22 04:11

Neil


This was the workaround I used: at the top of the .py file, I added:

import sys

if sys.version_info[0] == 3:
    from io import IOBase
    file = IOBase

So if Python 3 is being used, set file to be IOBase. Now isinstance(filehandler, file) will work correctly in Python 3, and for Python 2 it will work just like it always has.

Of course, this solution is extremely hackish and confusing, since it makes it look like IOBase is the Python 3 version of file, which is not the case. But it does solve the problem.

like image 33
jpyams Avatar answered Nov 13 '22 05:11

jpyams