Python:如何判断一个对象是否类似文件?
我正在为我的应用程序编写一些单元测试(使用unittest模块),想要写一个可以验证我调用的方法是否返回一个“像文件的”对象的东西。因为这不是一个简单的isinstance调用,所以我在想,确定这一点的最佳实践是什么?
大致来说:
possible_file = self.dao.get_file("anotherfile.pdf")
self.assertTrue(possible_file is file-like)
也许我需要关心这个文件对象具体实现了哪个接口,或者我想支持哪些让它像文件的方法?
谢谢,
R
3 个回答
检查一下返回的对象是否提供了你想要的接口。比如这样:
self.assert_(hasattr(possible_file, 'write'))
self.assert_(hasattr(possible_file, 'read'))
在Python的传统思维中,有一句话是“请求原谅比请求许可更容易”。换句话说,就是不要事先检查,而是直接尝试去做,如果出错了再处理这个错误。
不过,现在有了一种新的方法,就是使用一个输入输出的抽象基类来进行类型检查。这种方法是在大家意识到“鸭子类型”很不错的同时,有时候确实需要确认一下对象的类型。
在你的情况(单元测试)中,你可能想要直接尝试一下,看看效果如何:
thingy = ...
try:
thingy.write( ... )
thingy.writeline( ... )
...
thingy.read( )
except AttributeError:
...
其实没有一个“官方定义”来说明什么样的对象算是“足够像文件”,因为不同的文件样对象有不同的需求。例如,有的只需要 read
或 write
方法,而有的则需要一些特定的行读取方法……还有一些对象需要 fileno
方法,但像 StringIO
和 cStringIO
这些标准库里的“非常像文件的对象”就连这个方法都没有。总之,这个问题是个“灰色地带”,而不是简单的黑白分类!
所以,你需要先弄清楚你需要哪些方法。为了检查这些方法,我建议你定义一个自己的 FileLikeEnoughForMe
抽象基类,并使用 abstractmethod
装饰器来标记需要的方法。如果你使用的是 Python 2.6 或更高版本,可以用 isinstance
来检查对象是否属于这个类。现在这种做法比起一堆 hasattr
检查要更推荐,因为后者可读性差且更复杂(尤其是当你需要确保这些属性确实是方法时)。