我有一个方法可以检测行尾
def getLineEnding(filename):
ret = "rn"
with open(filename, 'r') as f:
f.readline()
ret = f.newlines
return ret
为了能够在不使用真实文件的情况下对其进行测试,我将其更改为:
def getLineEnding(filehandle):
filehandle.readline()
return filehandle.newlines
这适用于文件。但当我这样做时:
f = StringIO()
f.write('testrn')
f.seek(0)
f.readline()
print(f.newlines)
我得到None
我检查文件结尾的原因是我正在编写一个处理文本文件的程序,并且我希望保留原始的行结尾。
要回答您的问题,io.StringIO
的newline
参数的默认值与io.TextIOWrapper
(由open(..., 'r')
返回(的默认值不同。对于StringIO
,默认值是'n'
,而对于TextIOWrapper
,默认值为None
。文档解释了行为:
newline控制如何处理行尾。它可以是
None
、''
、'n'
、'r'
和'rn'
。它的工作原理如下:
- 从流中读取输入时,如果换行符为
None
,则启用通用换行符模式。输入中的行可以以'n'
、'r'
或'rn'
结束,这些行在返回给调用者之前被转换为'n'
。如果换行符为''
,则启用通用换行符模式,但换行符将返回给未翻译的调用者。如果换行符具有任何其他合法值,则输入行仅由给定的字符串终止,并且行结尾未经翻译返回给调用者- […]
因此,这意味着默认情况下TextIOWrapper
将翻译行尾,而StringIO
不会。则newlines
属性的文档为:
字符串、字符串元组或None,表示到目前为止翻译的换行符。[…]
因此,如果不执行转换,则不会设置此属性(StringIO
就是这样(。
解决方案是通过传递newline=None
来构造StringIO
对象,即
f = StringIO(newline=None)
则w.r.t.行结尾的行为将类似于TextIOWrapper
。
然而,如果目标是保持行结尾不变,则可以直接使用newline=''
返回未翻译的行结尾,如上文引用的文档所述。