我习惯了做print >>f,"hi there"。
然而,似乎print >>正受到抨击。上面这一行的推荐方法是什么?
更新:关于所有关于"
"的答案…这是通用的还是特定于Unix的?我应该在窗户上做"
"吗?
- 行尾在我的答案中有地址。
- "n"不是特定于Unix的。当文件以文本模式(默认)打开时,它将自动转换为当前平台的正确行尾。写入
"将产生
",这是错误的。
- 只需添加print-ord(os.linesep)语句即可查看ASCII代码(大多数UNIX系统上为10个)。
- @我相信,约翰西韦布的回答更正确,应该是选择的答案。
您应该使用自python 2.6以来可用的print()函数。+
1 2
| from __future__ import print_function # Only needed for Python 2
print("hi there", file=f) |
对于python 3,您不需要import,因为print()函数是默认的。
另一种选择是使用:
1 2 3 4 5
| f = open('myfile', 'w')
f.write('hi there
') # python will convert
to os.linesep
f.close() # you can omit in most cases as the destructor will call it |
引用python文档中有关换行的内容:
On output, if newline is None, any '
' characters written are translated to the system default line separator, os.linesep. If newline is '', no translation takes place. If newline is any of the other legal values, any '
' characters written are translated to the given string.
- 这在Windows上可以吗?(即,换行符)
- -1"如果要确定,请将os.linesep添加到字符串中,而不是将EDOCX1[5]添加到字符串中,这将需要newline="否则将在Windows上获取EDOCX1[6]。根本没有理由在os.linesep上浪费时间。
- @索林·斯巴尼亚:你的两句话都是很正确的,但绝对与(明确地)写os.linesep而不是
无关。静止- 1
- @索林:还是-1。在非Windows系统上,您只能从f.write(os.linesep)获得相同的结果。顺便说一下,您的代码不起作用,您需要模式='W'
- @索林:你的编辑添加写入模式当然是一个改进。然而,奇怪的是,你对os.linesep仍持不妥协态度。看看我的答案。顺便说一下,您引用的文档是3.x的,但此部分在文本模式下对2.x也是有效的:写入的任何'字符都会转换为系统默认行分隔符os.linesep*…Windows:写入os.linesep与写入
相同,其中包含
转换为os.linesep,即
,因此最终结果为
。
- @约翰,你说得对,我纠正了os.linesep错误。谢谢。
- 用f.close()完成此操作以关闭文件。只有这样,你才能看到所写的东西。
- 请不要告诉我,print("hi there",file=f)"方法是python3的内置方法。这让我觉得我需要搬到Python3
- @Sorin为什么第一种方法(使用file=f)比第二种方法(使用f.write)更可取?
- 当我使用此方法时,它将删除所有换行符。我怎样才能把它一行一行地写出来呢?
- 有人能告诉我未来是什么吗?:/I正在使用PY2.7和Learning 3.0..
- 附加的不是open('myfile','a')而不是open('myfile','w')?
- 不使用with语句是一种糟糕的做法。
- 我对这种方法的问题是,它在文件的最后一行添加了一个新行字符。移除它的最佳方法。
- @PSU:有什么不清楚的?关于open的文档有什么不清楚的?
- F是一个文件处理程序对象,您可以在文档中找到它。
- @PSU:查看open并读取它返回的内容。需要十秒钟。
- @Bradruderman,这是POSIX标准的一部分,用于定义文本文件中的"行",即文本文件中的每一行都必须以换行符(甚至最后一行)结束。
这应该简单到:
1 2 3
| with open('somefile.txt', 'a') as the_file:
the_file.write('Hello
') |
从文档中:
Do not use os.linesep as a line terminator when writing files opened in text mode (the default); use a single '
' instead, on all platforms.
一些有用的读物:
- with声明
- open()
- os(特别是os.linesep)
- 此示例优于打开/关闭示例。使用with是记住关闭文件的一种更安全的方法。
- 我不必打电话给the_file.close()?
- 不,你不知道:stackoverflow.com/questions/3012488/…
- @你为什么说"os.linesep.操作系统里有很多好东西!",你之前在帖子中建议不要使用它的时候?我怀疑这里的编辑,这可能是投票下降的原因。
- @霍斯史密斯:事件发生3.5年后,我可能记错了,但我当天编辑了文档中的段落,为感兴趣的读者留下了指向os.linesep文档的链接。我记得,2年后出现了反对票。
- @约翰西,我想你误解了我。我不是说你在他们投反对票后编辑的。如果你问人们为什么投票反对你,那你就没道理了。我怀疑的是,你在编辑中添加了关于为什么不使用os.linesep的警告,而忘记了你在广告中所宣传的os.linesep是如何拥有好东西的,而在本例中,只有os.linesep是没有用的,这在本例中是误导性的。人们可能投票反对你发送这样的信息:os.linesep在这种情况下很好。可以添加它作为文档,但可以发送混合消息。
- @我明白了。希望我最近的编辑能澄清我的意图。如果我的答案"相当无用和误导",请随意编辑。
- cli:python -c 'with open("file.txt","w") as file: file.write("Hello
")'。
- "文本模式(默认)"是指open与"w"一起使用,您仍然需要os.linesep与"wb"一起使用。
- @用户3226167:这是一个有趣的观点。但是为什么要打开一个二进制文件来写纯文本呢?
python文档建议这样做:
1 2
| with open('file_to_write', 'w') as f:
f.write('file contents') |
所以我通常是这样做的:)
docs.python.org的声明:
It is good practice to use the 'with' keyword when dealing with file
objects. This has the advantage that the file is properly closed after
its suite finishes, even if an exception is raised on the way. It is
also much shorter than writing equivalent try-finally blocks.
- 我不喜欢这样,当我需要把with嵌套在一个循环中时。这使得我在循环中不断地打开和关闭文件。也许我在这里遗漏了一些东西,或者这真的是这个特定场景中的一个缺点?
- 在with中循环怎么样?
关于os.linesep:
下面是一个未经编辑的精确的Windows python 2.7.1解释器会话:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| Python 2.7.1 (r271:86832, Nov 27 2010, 18:30:46) [MSC v.1500 32 bit (Intel)] on
win32
Type"help","copyright","credits" or"license" for more information.
>>> import os
>>> os.linesep
'
'
>>> f = open('myfile','w')
>>> f.write('hi there
')
>>> f.write('hi there' + os.linesep) # same result as previous line ?????????
>>> f.close()
>>> open('myfile', 'rb').read()
'hi there
hi there
'
>>> |
在Windows上:
正如预期的那样,os.linesep不会产生与'
'相同的结果。它不可能产生同样的结果。'hi there' + os.linesep相当于'hi there
',不相当于'hi there
'。
这很简单:使用
,它将自动转换为os.linesep。自从第一个从Python到Windows的端口以来,它就这么简单了。
在非Windows系统上使用os.linesep没有意义,它会在Windows上产生错误的结果。
不要使用os.linesep!
- 很好的例子——好奇你是不是一个ipython用户?格式化会话的好功能
- 我不完全确定你想告诉我们什么。os.linesep将返回操作系统定义的行术语字符(或字符串)。Windows默认使用
作为行尾。但是,可以识别单个。使用将提供完全可移植的输出,但在Windows上os.linesep并不是错误的。
- @Gusdor:重点是,如果在文本模式下在Windows中显式使用os.linesep,结果是
,这是错误的。"Windows使用…"毫无意义。C运行库(因此是python)在文本模式下输出时将
转换为
。其他软件的行为可能不同。并非所有在Windows上运行的软件在以文本模式读取时都将单独的
识别为行分隔符。Python确实如此。微软的记事本文本编辑器没有。
- @我想我明白你的意思。最坏的情况是,您的文件中有一个双
。我不知道后果会是什么。有争议的是,如果你在写文本模式,你将在其中阅读。在这一点上,额外的
是膨胀的,但是我通常为.NET编写的内容不多(只有行尾有标记),这允许我选择要与write line()一起使用的行术语。也许在textiographer上使用类似的方法可以避免这种混淆。
- 可以说,有人会读到它,而不是你,用一些米老鼠软件,将巴结额外的
。
- @gusdor您是从另一种语言来到python的吗?在这种语言中,使用''会导致在窗口上输出'',而不是'
'——因此它缺少哑文本编辑器所期望的'
'?正如约翰所说,这不是python的行为方式--"如果os.linesep说要做的话",则"n"会自动替换为"r"。因此,在这里明确地说os.linesep是"错误的"。它和Department of Redundancy Department相似。是的,你能做到。不,你不想。
- 我完全同意这应该是明确的。除非你自己设置,否则不要盲目地假设事情是正确配置的。在EOL的情况下,只做这件事并不容易。发送你所知道的接收者需要的信息。用于Unix的f.write('hi there
'),用于DOS的f.write('hi there
')
。我建议你建立一条输出线,比如outline ="Hi There!" +"
"
,然后简单地建立f.write(outline)。
我认为没有"正确"的方法。
我会用:
1 2
| with open ('myfile', 'a') as f: f.write ('hi there
') |
为了纪念蒂姆·托迪。
- 但操作人员可能想将其他内容写入文件。在这里,当with超出范围时,文件将被关闭。
- 那可能是open(..., 'a')甚至'at'。
- 嗯,是的。这就是与一起使用的想法。如果要保持文件打开,只需在开始时调用open,完成后调用close…
- @ MTRW。真的。手术正在追加。
- 就python而言,是rip tim toady——而且非常正确。
- 我刚才看到了这辆车。这解释了我对语言的失望。我已经用了五年多了,除了它的库,而且常常不顾语法。没有内联注释?神秘的班级结构?只有单线兰姆达斯?
- zen of perl可能有点矛盾。
在python 3中,它是一个函数,但是在python 2中,您可以将其添加到源文件的顶部:
1
| from __future__ import print_function |
然后你这样做
1
| print("hi there", file=f) |
如果你写了大量的数据,速度是一个问题,你可能应该使用f.write(...)。我做了一个快速的速度比较,它比执行大量写入时的print(..., file=f)快得多。
1 2 3 4 5 6 7 8 9 10
| import time
start = start = time.time()
with open("test.txt", 'w') as f:
for i in range(10000000):
# print('This is a speed test', file=f)
# f.write('This is a speed test
')
end = time.time()
print(end - start) |
在我的机器上,write平均完成时间为2.45秒,而print的完成时间约为9.76秒的4倍。也就是说,在大多数现实场景中,这不会是一个问题。
如果你选择和print(..., file=f)一起去,你可能会发现你会不时地想要压制新行,或者用别的东西来代替新行。这可以通过设置可选的end参数来实现,例如:
1 2 3 4
| with open("test", 'w') as f:
print('Foo1,', file=f, end='')
print('Foo2,', file=f, end='')
print('Foo3', file=f) |
无论您选择哪种方式,我都建议使用with,因为它使代码更容易阅读。
更新:这种性能上的差异是由这样一个事实来解释的:write是高度缓冲的,在任何写入磁盘之前都会返回(见这个答案),而print可能使用行缓冲。对此的一个简单测试是检查长时间写入的性能,在这种情况下,行缓冲的缺点(在速度方面)将不那么明显。
1 2 3 4 5 6 7 8 9 10
| start = start = time.time()
long_line = 'This is a speed test' * 100
with open("test.txt", 'w') as f:
for i in range(1000000):
# print(long_line, file=f)
# f.write(long_line + '
')
end = time.time()
print(end - start,"s") |
性能差异现在变得更加不明显,write的平均时间为2.20秒,print的平均时间为3.10秒。如果需要连接一组字符串以获得这种looong行性能,那么使用print效率更高的用例就比较少见了。
因为3.5,您也可以使用pathlib:
Path.write_text(data, encoding=None, errors=None)
Open the file pointed to in text mode, write data to it, and close the file:
1 2 3
| import pathlib
pathlib.Path('textfile.txt').write_text('content') |
当您说行时,它意味着一些序列化字符结束于'字符。行应该在某个点最后,所以我们应该在每行的末尾考虑''。以下是解决方案:
1 2
| with open('YOURFILE.txt', 'a') as the_file:
the_file.write('Hello') |
在每次写入后的附加模式下,光标移动到新行,如果要使用"w"模式,应在write()函数的末尾添加'字符:
1 2
| the_file.write('Hello'+'
') |
- "在每次写入后的附加模式下,光标移动到新行"–不,不是。
也可以使用io模块,如下所示:
1 2 3 4 5
| import io
my_string ="hi there"
with io.open("output_file.txt", mode='w', encoding='utf-8') as f:
f.write(my_string) |