在Python中,对于内部接口,应该使用BytesIO还是bytes?

8
我正在尝试确定在我的代码中使用的最佳内部接口,特别是如何处理文件内容。实际上,文件内容只是二进制数据,因此字节足以表示它们。
我将文件存储在不同的远程位置,因此有几个不同的类用于读写。我正在尝试确定用于我的函数的最佳接口。最初我使用文件路径,但这是次优的,因为它意味着始终使用磁盘(这意味着大量笨拙的临时文件)。
代码中有几个区域具有相同的要求,并直接使用从此接口返回的任何内容。因此,无论我选择什么抽象都会触及相当多的代码。
使用BytesIO和bytes之间有哪些权衡?
def put_file(location, contents_as_bytes):
def put_file(location, contents_as_fp):
def get_file_contents(location):
def get_file_contents(location, fp):

在实践中,我发现使用文件类接口(BytesIO等)需要一些管理开销,例如seek(0)等。这引发了以下问题:

  • 在开始之前还是结束之后进行seek更好?
  • 是将seek指向开头还是仅从文件的当前位置操作?
  • 是否应该tell()以保持位置不变?
  • shutil.copyfileobj这样的内容看起来没有进行寻址。

使用文件类接口的一个优点是可以在检索数据时传递写入的文件指针,这似乎提供了很大的灵活性。

def get_file_contents(location, write_into=None):
    if not write_into:
        write_into = io.BytesIO()

    # get the contents and put it into write_into

    return write_into

get_file_contents('blah', file_on_disk)
get_file_contents('blah', gzip_file)
get_file_contents('blah', temp_file)
get_file_contents('blah', bytes_io)
new_bytes_io = get_file_contents('blah')
# etc

在Python中设计接口时,使用BytesIO是否比使用固定字节更优呢?

1个回答

5
io.BytesIO 对象的好处在于它们实现了一个相对通用的接口(通常被称为“类文件”对象)。BytesIO 对象有一个内部指针(其位置由 tell() 返回),每次调用 read(n) 时,指针向前移动 n 个字节。例如:
import io

buf = io.BytesIO(b'Hello world!')
buf.read(1) # Returns b'H'

buf.tell()  # Returns 1
buf.read(1) # Returns b'e'

buf.tell() # Returns 2

# Set the pointer to 0.
buf.seek(0)
buf.read() # This will return b'H', like the first call.

在您的使用场景中,bytes对象和io.BytesIO对象可能都不是最佳解决方案。它们会将文件的完整内容读入内存。
相反,您可以查看tempfile.TemporaryFilehttps://docs.python.org/3/library/tempfile.html)。

感谢您的输入。我最终使用了字节和类似文件的对象的组合。关于tempfile的好处是很有道理的 - 使用类似文件的对象可以在需要时灵活地使用tempfile,这可能会为某些用例提供更好的时间/空间权衡。 - Aidan Kane
1
最后一个 buf.read() 将返回整个字符串。如果省略 size 参数或使用负值,它将读取直到 EOF。我认为你的意思是 buf.read(1) - Caleb Fenton

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