检查对象是否与Python中的文件类似

2024-04-28 05:03:30 发布

您现在位置:Python中文网/ 问答频道 /正文

File-like objects是Python中的对象,其行为类似于一个真实的文件,例如具有read()和write方法(),但具有不同的实现。它是Duck Typing概念的实现。

在需要文件的地方允许类似文件的对象出现在任何地方,这样就可以使用StringIO或Socket对象来代替真正的文件,这被认为是一种良好的实践。所以这样的检查是不好的:

if not isinstance(fp, file):
   raise something

检查对象(例如方法的参数)是否“类似文件”的最佳方法是什么?


Tags: 文件对象方法概念typingreadifobjects
3条回答

对于3.1+,请执行以下操作之一:

isinstance(something, io.TextIOBase)
isinstance(something, io.BufferedIOBase)
isinstance(something, io.RawIOBase)
isinstance(something, io.IOBase)

对于2.x来说,“类似文件的对象”是一个很模糊的东西,无法检查,但是您正在处理的任何函数的文档都可能告诉您它们实际需要什么;如果没有,请阅读代码。


正如其他答案所指出的,首先要问的是你到底在查什么。通常,EAFP是足够的,而且更习惯。

The glossary说“类文件对象”是“文件对象”的同义词,这最终意味着它是the ^{} module中定义的三个abstract base classes中的一个实例,它们本身都是IOBase的子类。所以,检查的方法正是上面所示的。

(但是,检查IOBase不是很有用。你能想象这样一种情况吗:你需要把一个像read(size)这样的实际文件与一个名为read的不象文件的参数函数区分开来,而不需要区分文本文件和原始二进制文件?所以,实际上,您几乎总是想检查,例如,“是文本文件对象”,而不是“是类似文件的对象”。)


对于2.x,虽然io模块自2.6+以来就已经存在,但内置文件对象不是io类的实例,stdlib中也不是任何类似文件的对象,也不是您可能遇到的大多数类似第三方文件的对象。“类文件对象”的含义没有官方定义;它只是“类似于内置的file object”,不同的函数用“类”表示不同的东西。这些函数应该记录它们的含义;如果它们没有,则必须查看代码。

但是,最常见的含义是“has read(size)”、“has read()”或“is a iterable of strings”,但是一些旧库可能期望readline而不是其中之一,有些库喜欢您给它们的close()文件,有些库希望如果fileno存在,则可以使用其他功能,等等,对于write(buf)也同样如此(尽管在这个方向上有更少的选择)。

正如其他人所说,你一般应该避免这样的检查。一个例外是,对象可能是合法的不同类型,并且您希望根据类型有不同的行为。EAFP方法并不总是在这里工作,因为一个对象可能看起来像不止一种类型的duck!

例如,初始化程序可以获取自己类的文件、字符串或实例。然后您可能会得到如下代码:

class A(object):
    def __init__(self, f):
        if isinstance(f, A):
            # Just make a copy.
        elif isinstance(f, file):
            # initialise from the file
        else:
            # treat f as a string

在这里使用EAFP可能会导致各种微妙的问题,因为在抛出异常之前,每个初始化路径都会部分运行。 从本质上说,这种构造模仿函数重载,因此不是很Python,但如果小心使用,它可能会很有用。

顺便说一句,在Python 3中,不能用同样的方法检查文件。你需要像isinstance(f, io.IOBase)这样的东西。

除非有特殊要求,否则在代码中进行这种检查通常是不好的。

在Python中,输入是动态的,为什么需要检查对象是否像文件一样,而不是像文件一样使用它并处理结果错误?

无论如何,您可以执行的任何检查都将在运行时进行,因此执行类似于if not hasattr(fp, 'read')的操作并引发一些异常,所提供的实用性不会比仅调用fp.read()和在方法不存在时处理结果属性错误多多少。

相关问题 更多 >