如何检查一个对象是否是'file'实例?

3 投票
4 回答
6038 浏览
提问于 2025-04-16 04:32

以前在Python(2.6)中,我们可以这样询问:

isinstance(f, file)

但是在Python 3.0中,file这个东西被去掉了

那么现在检查一个变量是否是文件的正确方法是什么呢?更新文档里没有提到这个……

4 个回答

1

通常情况下,你不需要去检查一个对象的类型,可以使用“鸭子类型”来处理。也就是说,直接调用 f.read(),如果出现错误,就让错误继续传播下去——这可能是你代码中的一个bug,或者是调用代码中的bug。例如,如果你给 json.load() 一个没有 read 属性的对象,它会抛出 AttributeError 错误。

如果你需要区分几种可以接受的输入类型,可以使用 hasattr/getattr 来帮助你:

def read(file_or_filename):
    readfile = getattr(file_or_filename, 'read', None)
    if readfile is not None: # got file
       return readfile()
    with open(file_or_filename) as file: # got filename
       return file.read()

如果你想支持一种情况,即 file_of_filename 可能有一个 read 属性,但这个属性的值是 None,那么你可以在 file_or_filename.read 上使用 try/except,注意:这里不需要加括号,因为并没有实际调用——例如,ElementTree._get_writer()

如果你想检查某些特定的保证,比如只进行一次系统调用(io.RawIOBase.read(n),当 n > 0 时),或者没有短写(io.BufferedIOBase.write()),或者读写方法是否接受文本数据(io.TextIOBase),那么你可以使用 isinstance() 函数,结合 io 模块中定义的 ABCs,例如,看看 saxutils._gettextwriter() 是怎么实现的

5

在Python3中,你可以使用io模块,而不是file,然后你可以这样写:

import io
isinstance(f, io.IOBase)
5
def read_a_file(f)
    try:
        contents = f.read()
    except AttributeError:
        # f is not a file

根据你计划使用的方法来替换 read。如果你预计大约98%的情况下会处理一个类似文件的对象,这样做是最优的。如果你认为会有超过2%的情况处理到非文件对象,那么正确的做法是:

def read_a_file(f):
    if hasattr(f, 'read'):
        contents = f.read()
    else:
        # f is not a file

这正是你如果有一个 file 类可以测试时会做的事情。(顺便说一下,我在2.6版本中也有 file)请注意,这段代码在3.x版本中也能正常工作。

撰写回答