python / python/cpython

'_Stream' object has no attribute 'seekable'

未关闭
#124,293 7 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

3.12 3.13 3.14 stdlib type-bug
主要语言
Python
星标
77.2k
派生
35.9k
PR 合并指标
PR 指标待抓取

描述

Bug report

Bug description:

From a recent application, I have found tarfile._Stream doesn't have a seekable() method. A quick reproduction of the problem is as follows:

import tarfile
import io

data = b"Test data."
buf = io.BytesIO()
with tarfile.open(fileobj=buf, mode="w") as tf:
    ti = tarfile.TarInfo(name="test.txt")
    ti.size = len(data)
    tf.addfile(tarinfo=ti, fileobj=io.BytesIO(data))

buf.seek(0)
tf = tarfile.open(fileobj=buf, mode="r|")
for entry in tf:
    f = tf.extractfile(entry)  # `f` is in type of `class ExFileObject(io.BufferedReader)`
    f.seekable()  # AttributeError
    f.seek(0)  # AttributeError

Output:

Traceback (most recent call last):
  File "a.py", line 17, in <module>
    print(f.seekable())
  File "AppData\Local\Programs\Python\Python310\lib\tarfile.py", line 641, in seekable
    return self.fileobj.seekable()
AttributeError: '_Stream' object has no attribute 'seekable'

When opening tarfile with r| mode, ExFileObject.fileobj would be a _Stream object. So when calling ExFileObject.seekable(), as _Stream object dun have seekable() method, it will raise AttributeError.

Also, as BufferedReader.seek() will also check its raw.seekable() (i.e. in Modules/_io/bufferedio.c, func _io__Buffered_seek_impl(), there is a call to _PyIOBase_check_seekable(state, self->raw, Py_True)), f.seek() in the above example will also raise AttributeError.

I have thought of if we can simply define seekable() in _Stream object, but as it is only "forward-seekable", I am not sure if directly returning a true/false in _Stream.seekable() is appropriate or not. However, this issue does break the IOBase interface and there should be a solution.

Thanks for everyone's time and effort for looking into this.

CPython versions tested on:

3.10, 3.11, 3.12, 3.13, CPython main branch

Operating systems tested on:

Linux, Windows

贡献指南

打开贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

调研方向

首先在 r| mode 下运行提供的 tarfile 重现,然后检查 tarfile.py 中的 tarfile._Stream 和 ExFileObject,以及 Modules/_io/bufferedio.c 中的 _io__Buffered_seek_impl()。确定仅支持向前读取的流应采用的适当 seek 行为,并验证报告的 seekable() 和 seek() AttributeErrors 已得到解决,同时不会破坏流式处理语义。

由索引模型根据 Issue 内容生成。

评估

技术栈
python
领域
backend
Issue 类型
缺陷
难度
4/5
预计耗时
3-5 天
活跃度
停滞
描述清晰度
基本清楚
新手友好度
38/100

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。