Python中的文件对象究竟是什么?

52

根据标准库json模块的文档

json.dump(obj, fp, *, skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, cls=None, indent=None, separators=None, default=None, sort_keys=False, **kw)

使用此转换表将obj序列化为JSON格式流,写入fp(支持.write()类文件对象)。

这个描述具体是什么意思?哪些对象类型是支持".write()"和"类文件"的?


4
好的,你自己已经回答了你的问题:任何支持正确调用 read()、write() 或两者都支持的对象都被认为是类似文件的对象。它可以是任何你喜欢的对象——这就是鸭子类型的乐趣所在。 - Jim Brissom
我认为没有任何官方标准。大多数接口应该明确指定所需的功能。如果您想知道某个其他东西是否支持所需的内容,您将不得不查看其文档或阅读其源代码。 - martineau
2
“类文件对象”实际上是精确定义的 - chepner
在最近版本的文档中,这段文字已经更新为json.load不再提及“类文件对象”: “使用此转换表将fp(包含JSON文档的支持.read()的文本文件或二进制文件)反序列化为Python对象。”然而,json.dump的描述仍然涉及该概念。文档也已经很久没有使用simplejson名称了。 - Karl Knechtel
历史注释:json标准库模块是在Python 2.6中添加的,其文档没有包含解释“类文件对象”概念的链接,也没有在词汇表中提到。该库来自第三方项目simplejson,其中某个版本被整体合并;当时的文档可能提到了simplejson名称,但当前2.6的文档没有。(2.5及之前的旧版文档似乎根本不包含词汇表。) - Karl Knechtel
1
我编辑了这个问题,展示了一个当前文档中提及(并链接)这个概念的示例,并删除了关于问题动机的部分(因为它与修改后的示例不符)。如果你在这里是因为正在尝试处理来自Web请求的JSON(或关闭一个重复的问题),就像原始提问者的动机一样,请参考权威指南:如何解析和使用JSON? - Karl Knechtel
6个回答

26

词汇表中:

类文件对象

文件对象的同义词。

文件对象是什么:

文件对象

一种向底层资源公开文件导向API(例如read()或write()方法)的对象。根据创建方式,文件对象可以介导对真实磁盘文件或另一类型存储或通信设备(例如标准输入/输出、内存缓冲区、套接字、管道等)的访问。文件对象也称为类文件对象或流。

实际上有三类文件对象:原始二进制文件、缓冲二进制文件和文本文件。它们的接口在io模块中定义。使用open()函数是创建文件对象的规范方式。


8
“使用诸如”...我想这真正将我们带回到最初的问题:这一系列方法究竟是什么?例如,“模式”是否是此对象的必需属性? - Klaas van Schelven
@KlaasvanSchelven 遗憾的是,这可能取决于底层操作系统或文件系统。 - chepner
我想这个问题在这一点上是修辞性的;-) 关键是我们对“精确定义”的含义有不同的看法。 - Klaas van Schelven
很不幸,这可能取决于底层操作系统或文件系统。那么它就不是API了。或者至少不是单一的API。API是一个严格的接口;它不是有条件的。 - cowlinator

19

IO类层次结构是Python IO模块文档中的一个部分,其中列出了不同类型文件对象的内置方法和存根方法。

基本上,这里有一个抽象基类的层次结构:

要实现类似文件的对象,您应该从IOBase的三个后代类之一派生子类,但不是从IOBase本身派生。有关尝试确定给定文件对象属于哪个类的信息,请参见此答案

每个类都提供各种存根方法和混合方法:

类别 桩方法 混入
IOBase fileno, seek, truncate close, closed, __enter__, __exit__, flush, isatty, __iter__, __next__, readable, readline, readlines, seekable, tell, writable, writelines
RawIOBase readinto, write read, readall
BufferedIOBase detach, read, read1, write readinto, readinto1
TextIOBase detach, read, readline, write encoding, errors, newlines

这些方法的文档可以在上面链接的类的文档中找到。


表格来源:https://docs.python.org/3/library/io.html#class-hierarchy - cowlinator

17
在Python中,文件对象是一个暴露API的对象,其具有执行通常在文件上完成的操作的方法,例如read()write()
在问题的示例中:simplejson.load(fp, ...),作为fp传递的对象只需要具有像文件上的read()一样的可调用方法(即接受一个可选参数size并返回strbytes对象)。
但是,这不一定是一个真正的文件,只要它有一个read()方法即可。 类似文件的对象只是文件对象的同义词。请参见Python术语表

13

类文件对象主要包括StringIO对象、连接的套接字以及实际的文件对象。

如果一切顺利,urllib.urlopen()将返回支持必要方法的类文件对象。


29
必要的方法是最重要的方面。哪些方法? - cowlinator

5
这是Python标准库中所有类文件对象的API文档(截至版本3.10.5)。
# All file-like objects inherit the IOBase interface:
# Documented at https://docs.python.org/3/library/io.html#io.IOBase .
    close() -> None
    closed() -> bool # Implemented as @property `closed`
    fileno() -> int
    flush() -> None
    isatty() -> bool
    readable() -> bool
    readline(size: int = -1) -> Union[str, bytes]
    readlines(hint: Union[int, None] = None) -> list
    seek(pos: int, whence: int = io.SEEK_SET) -> int # SEEK_SET is 0
    seekable() -> bool
    tell() -> int
    truncate(pos: int = None) -> int # The parameter is named "size" in class FileIO
    writable() -> bool
    writelines(lines: list) -> None
    __del__() -> None
# Documented at https://docs.python.org/3/library/io.html#class-hierarchy .
    __enter__()
    __exit__(*args) -> None:
    __iter__()
    __next__() -> Union[str, bytes]
# Documented in paragraph at https://docs.python.org/3/library/io.html#io.IOBase .
# Note that while the documentation claims that the method signatures 
# of `read` and `write` vary, all file-like objects included in the Python 
# Standard Library have the following exact method signatures for `read` and `write`:
    read(size: int = -1) -> Union[str, bytes]
    write(b: Union[str, bytes]) -> int # The parameter is named "s" in TextIOBase

特定的文件对象可能实现更多方法,但这是所有文件对象共有的一部分方法。


2
这仅适用于标准库。在Python世界的许多地方(甚至在docs.python.org上),"类似文件对象"是一个更宽泛的概念。在许多情况下,具有read(size: int)方法就足够了。 - Lutz Prechelt
我更新了我的答案,只涉及标准库。 - cowlinator

-1

1
@user313439,不用谢。只是为了明确起见,您应该在字符串中使用dumps和loads。在您的情况下添加StringIO是额外的开销。 - kevpie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接