我正在研究测试一些作用于文件的代码的方法,但我想编写一些仅依赖于源文件中的特定字符串而不是文件系统中某处的特定文件的测试。
我知道可以通过 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
还是有更好的方法?
最佳答案
您可以使用 BytesIO
和 TextIOWrapper
模拟真实文件的行为:
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/