python - 如何在 Python 中模拟以文本模式打开的文件

标签 python python-3.x

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

我知道可以通过 io.StringIO 为字符串提供类似 file 的流接口(interface)。

问题在于操作不遵循相同的语义。 例如,file.seek()file.read() 的组合会产生不同的结果,具体取决于文件对象是否来自 open() 或来自 io.StringIO 对于包含非 ASCII 字符的字符串:

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() 在用 open(),而对于 io.StringIO,它遵循 str 语义。

我明白,出于性能原因,让 seek() 遵循 str 语义是不切实际的,即使文件以文本模式打开也是如此。

因此,我的问题是:如何在 bytes 语义之后使用 seek 方法获得等效的 io.StringIO()?我必须自己重写 io.StringIO 还是有更好的方法?

最佳答案

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

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))
        # εζηθικλμ

关于python - 如何在 Python 中模拟以文本模式打开的文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57510419/

相关文章:

Python源文件组织

python - Django - 将音轨添加到页面

python - 如何让 Nose2 测试在 Visual Studio Code 上运行?

Python将具有多个键的Dict转换为Dataframe

Python 套接字服务器失败

python - 使用 re(正则表达式)仅解析一行

python - 仅当列中的特定值是唯一的时,如何替换它?

python - 使用 beautifulsoup 从标签 <a> 获取字符串

python - asyncio create_task 永远运行

python - BeautifulSoup 返回意外的额外空格