首页 > 解决方案 > 如何在 Python 中模拟以文本模式打开的文件

问题描述

我正在研究测试一些作用于文件的代码的方法,但我想编写一些仅依赖于源文件中的特定字符串而不是文件系统中某处的特定文件的测试。

我知道可以file通过io.StringIO.

问题是操作不遵循相同的语义。例如,根据文件对象是来自还是来自包含非 ASCII 字符的字符串,组合file.seek()和会产生不同的结果:file.read()open()io.StringIO

import io

#      'abgdezhjiklmnxoprstufqyw'
text = 'αβγδεζηθικλμνξoπρστυφχψω'


with open('test.txt', 'w') as file_obj:
    file_obj.write(text)


with open('test.txt', 'r') as file_obj:
    file_obj.seek(8)
    print(file_obj.read(8))
# εζηθικλμ


with io.StringIO(text) as file_obj:
    file_obj.seek(8)
    print(file_obj.read(8))
# ικλμνξoπ

仅 ASCII 字符串不会出现此问题:

import io

text = 'abgdezhjiklmnxoprstufqyw'


with open('test.txt', 'w') as file_obj:
    file_obj.write(text)


with open('test.txt', 'r') as file_obj:
    file_obj.seek(8)
    print(file_obj.read(8))
# iklmnxop


with io.StringIO(text) as file_obj:
    file_obj.seek(8)
    print(file_obj.read(8))
# iklmnxop

显然,这是由于在打开文件的情况下参数.seek()遵循bytes语义,而它遵循语义。offsetopen()io.StringIOstr

我确实理解,出于性能原因,即使文件以文本模式打开也不具有seek()以下语义是不切实际的。str

因此,我的问题是:如何使用遵循语义io.StringIO()的方法获得等价物?我必须超越自己还是有更好的方法?seekbytesio.StringIO

标签: pythonpython-3.x

解决方案


您可以使用BytesIOandTextIOWrapper来模拟真实文件的行为:

text = 'αβγδεζηθικλμνξoπρστυφχψω'

with io.BytesIO(text.encode('utf8')) as binary_file:
    with io.TextIOWrapper(binary_file, encoding='utf8') as file_obj:
        file_obj.seek(8)
        print(file_obj.read(8))
        # εζηθικλμ

推荐阅读