Python:确定对象是否类似于文件?

Python:确定对象是否类似于文件?,python,file,types,Python,File,Types,我正在为我的应用程序编写一些单元测试(使用unittest模块),并希望编写一些东西来验证我调用的方法是否返回“类似文件”的对象。由于这不是一个简单的isinstance调用,我想知道确定这一点的最佳实践是什么 因此,概括地说: possible_file = self.dao.get_file("anotherfile.pdf") self.assertTrue(possible_file is file-like) 也许我必须关心这个文件对象实现了哪个特定的接口,或者哪些方法使它成为我想要

我正在为我的应用程序编写一些单元测试(使用unittest模块),并希望编写一些东西来验证我调用的方法是否返回“类似文件”的对象。由于这不是一个简单的isinstance调用,我想知道确定这一点的最佳实践是什么

因此,概括地说:

possible_file = self.dao.get_file("anotherfile.pdf")
self.assertTrue(possible_file is file-like)
也许我必须关心这个文件对象实现了哪个特定的接口,或者哪些方法使它成为我想要支持的文件

谢谢


R

检查返回的对象是否提供了您要查找的接口。例如:

self.assert_(hasattr(possible_file, 'write'))
self.assert_(hasattr(possible_file, 'read'))

Python的经典思维方式是请求原谅比允许更容易。换句话说,不要检查,捕获由写入引起的异常

新方法是在
isinstance
检查中使用。这是在人们意识到duck类型非常棒时引入的,但有时确实需要实例检查

在您的案例(单元测试)中,您可能想尝试一下,看看:

thingy = ...
try:
    thingy.write( ... )
    thingy.writeline( ... )
    ...
    thingy.read( )
except AttributeError:
    ...
对于什么对象“足够像文件”没有“官方定义”,因为像文件对象的各种用途有着如此不同的要求——例如,一些只需要
read
write
方法,另一些则需要各种行读取方法的子集。。。所有的方法都需要
fileno
方法,而标准库中
StringIO
cStringIO
模块提供的“非常类似文件的对象”甚至无法提供这种方法。这绝对是一个“灰色阴影”的问题,不是一个黑白分类法


因此,您需要确定需要哪些方法。为了检查它们,我建议使用
abstractmethod
decorators定义您自己的
filelikeeoughtforme
,并使用
isinstance
检查该类的对象,如果您使用的是Python 2.6或更高版本:这是目前推荐的习惯用法,而不是一堆可读性较差且更复杂的
hasattr
检查(当适当地加强这些属性实际上是方法等的检查时;-)。

尝试写入文件在单元测试上下文中可能不合适。+1用于经典和文艺复兴思想patterns@Ned:真的吗?如果您正在实现一个类似文件的类,那么您肯定应该测试它是否写下了您给它的内容?但是如果你真的不想这样,那么你可以使用
hasattr
@Ned,这不取决于文件编写的实际操作吗?i、 e.单元测试不应该在测试后“清理”以查看程序的该部分是否真的写了吗?@Wayne,@Katrielex:是的,您可能想对其进行写入,并且可能会根据文件的内容自动清理。我的观点是,典型编程中的逻辑(请求原谅)在单元测试中可能不合适,这取决于测试试图完成什么。就这些。除非你确定你想要,否则不要这样做。是的,我不会那样做。但是他想知道一种方法来检查是否有类似文件的东西,而不是将它用作文件。嗨,亚历克斯,谢谢你的指点,这是很有趣的东西,尽管我仍然在想它。您是否建议将其用于单元测试,还是将其作为管理应用程序中类似文件的对象的一般方法?@Richard,我自己在Python中使用ABC时几乎没有“弄湿”过(尽管与Haskell类型类、C++抽象基类、Java接口等的类比确实对我有所帮助;-)因此,在这种情况下,我不能(目前)坚定地推荐它们。我认为他们会很好(同样通过类比我非常熟悉的替代品),但我需要在“我的腰带下”与他们进行更多的现实斗争,以使我对任何一种方式都充满信心;-)。但是,出于测试目的,我已经知道它们是“猫的睡衣”,也就是说,非常好而且非常有用。arg-注释中没有代码标记@Richard,你看过上的代码示例了吗?特别是
MyIterable
示例及其对
\uuuuu子类hook\uuuuuu
的重写——它显示了如何检查某些方法的存在(尽管这是一个简化示例,没有检查它们是否为方法)。一般来说,这不是使用ABC的最佳方式,因为缺乏任何明确的注册(或子类化)会使您失去验证意图的关键优势(著名的“绘制方法的问题”),但如果您正在检查是否存在,则在2.6+中就是这样做的。