将行写入文件的正确方法?


1069

我已经习惯了 print >>f, "hi there"

但是,似乎print >>已经弃用了。推荐使用哪种方法进行上述操作?

更新:关于...的所有这些答案,"\n"这是通用的还是特定于Unix的?IE,我应该"\r\n"在Windows上运行吗?


11
“ \ n”不是特定于Unix的。当以文本模式(默认)打开文件时,它将自动转换为当前平台的正确行尾。写“ \ r \ n”将产生“ \ r \ r \ n”,这是错误的。
D Coetzee

只需添加print ord(os.linesep)语句即可查看ascii代码(在大多数UNIX系统上为10)
Stefan Gruenwald

您为什么认为它已被弃用?
xxx ---

Answers:


1152

这应该很简单:

with open('somefile.txt', 'a') as the_file:
    the_file.write('Hello\n')

从文档:

os.linesep写入以文本模式打开的文件时(默认),请勿用作行终止符;在所有平台上都使用一个'\ n'代替。

一些有用的读物​​:


36
此示例比打开/关闭示例更好。使用with是记住关闭文件的更安全的方法。
2014年

18
我不必打电话the_file.close()吗?
侯赛因2014年


@Johnsyweb为什么在帖子的前面部分建议不要使用“ os.linesep。操作系统中有很多好东西!”,为什么呢?我怀疑这里有修改,这可能是投票否决的原因。
Horse SMith 2014年

1
@ user3226167:这很有趣。但是,为什么要打开一个二进制文件来写纯文本呢?
Johnsyweb '17

961

您应该使用print()Python 2.6+以上版本提供的功能

from __future__ import print_function  # Only needed for Python 2
print("hi there", file=f)

对于Python 3,您不需要import,因为该 print()功能是默认设置。

替代方法是使用:

f = open('myfile', 'w')
f.write('hi there\n')  # python will convert \n to os.linesep
f.close()  # you can omit in most cases as the destructor will call it

引用Python文档中有关换行符的内容:

在输出中,如果换行符为None,则所有'\n'写入的字符都会转换为系统默认的行分隔符os.linesep。如果newline是'',则不会进行翻译。如果换行符是其他任何合法值,'\n'则将写入的所有字符转换为给定的字符串。


35
-1“如果要确定,请在字符串中添加os.linesep而不是\n”,将需要newline =“”,否则将\r\r\n在Windows上运行。根本没有理由对os.linesep感到困惑。
约翰·马钦

7
@Sorin:您的添加写模式的编辑当然是一种改进。但是,您奇怪地对os.linesep保持不变。看我的答案。顺便说一句,您引用的文档适用于3.x,但此部分在文本模式下也适用于2.x:将写入的所有“ \ n”字符都转换为系统默认的行分隔符os.linesep *。 ..视窗:写os.linesep是一样的文字\r\n包含\n被翻译成os.linesep是\r\n这样最终的结果是\r\r\n
约翰·马钦

7
@约翰,您是对的,我更正了os.linesep错误。谢谢。
索林2011年

3
对于追加open('myfile','a')不是open('myfile','w')吗?
NeDark

6
@BradRuderman这是构成文本文件中“行” 的POSIX标准的一部分,即文本文件中的每一行都必须以换行符(甚至最后一行)结尾。
惠勒

116

Python文档建议是这样的:

with open('file_to_write', 'w') as f:
    f.write('file contents\n')

所以这就是我通常的方式:)

来自docs.python.org的声明:

在处理文件对象时,最好使用'with'关键字。这样做的好处是,即使在执行过程中引发了异常,文件在其套件完成后也将正确关闭。它也比编写等效的try-finally块短得多。


1
当我需要将with内部嵌套在循环中时,我不喜欢这种方式。这使我在循环中不断打开和关闭文件。也许我在这里错过了一些东西,或者这在特定情况下确实是不利的?
西伯斯赌博

38
在with中循环如何?
j7nn7k 2016年

@ j7nn7k for fd中的行:
momstouch

86

关于os.linesep:

这是Windows上未经编辑的Python 2.7.1解释器的确切会话:

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
'\r\n'
>>> f = open('myfile','w')
>>> f.write('hi there\n')
>>> f.write('hi there' + os.linesep) # same result as previous line ?????????
>>> f.close()
>>> open('myfile', 'rb').read()
'hi there\r\nhi there\r\r\n'
>>>

在Windows上:

正如预期的那样,os.linesep确实产生相同的结果一样'\n'。它不可能产生相同的结果。'hi there' + os.linesep等同于'hi there\r\n'等同于'hi there\n'

就是这么简单:使用\n它将自动转换为os.linesep。自从将Python首次移植到Windows以来,事情就变得如此简单。

在非Windows系统上使用os.linesep是没有意义的,并且在Windows上会产生错误的结果。

请勿使用os.linesep!


很好的例子-好奇您是否是ipython用户?格式化会话的好功能
Alvin

我不确定您要在这里告诉我们什么。os.linesep将返回操作系统定义的行术语字符(或字符串)。Windows默认使用\ r \ n作为行尾。但是,一个\ n被识别。使用\ n将提供完全可移植的输出,但是os.linesep在Windows上没有错。
Gusdor

5
@Gusdor:关键是,如果您os.linesep在Windows中以文本模式显式使用,则结果\r\r\n是错误的。“ Windows使用...”是没有意义的。C运行时库(以及Python)在文本模式下转换\n\r\non输出。其他软件的行为可能有所不同。\n在文本模式下阅读时,并非所有Windows上运行的软件都将孤行识别为行分隔符。Python确实如此。微软的记事本文本编辑器没有。
John Machin

6
可以说有人会用一些米老鼠软件而不是你来读它,而不是你\r……
约翰·马钦

2
@Gusdor您是从另一种语言进入python吗,在其中使用'\ n'会在窗口上输出'\ n'而不是'\ r \ n'-因此它缺少哑巴预期的'\ r'文字编辑器?正如John所说,这不是Python的行为方式-如果os.linesep这样做的话,'\ n'将自动替换为'\ r \ n'。因此,在这里明确地说os.linesep “错误的”。就像Department of Redundancy Department。是的,你可以做到。不,你不想。
ToolmakerSteve

55

我认为没有“正确”的方法。

我会用:

with open ('myfile', 'a') as f: f.write ('hi there\n')

在纪念蒂姆·托迪(Tim Toady)中


但是OP可能想向文件中写入其他内容。当with超出范围时,此处文件将关闭。
基思(Keith)

那可能想要成为open(..., 'a')甚至'at'
mtrw 2011年

5
恩,是的。这就是使用with的想法。如果您想保持文件打开状态,只需在开始时调用open并在完成后调用close ...
Hyperboreus,

1
@mtrw。真正。OP正在追加。
Hyperboreus

1
就python而言,是RIP Tim
Toady-

21

在Python 3中,它是一个函数,但是在Python 2中,您可以将其添加到源文件的顶部:

from __future__ import print_function

那你做

print("hi there", file=f)

17

如果您要写入大量数据,并且速度是一个问题,那么您可能应该考虑一下f.write(...)。我进行了快速的速度比较,它比print(..., file=f)执行大量写操作时要快得多。

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\n')
end = time.time()
print(end - start)

write我的机器上,平均完成print时间为2.45秒,而耗时则为(9.76s)的4倍。话虽这么说,在大多数现实情况下这都不是问题。

如果您选择使用,print(..., file=f)您可能会发现您可能会不希望取消换行符,或将其替换为其他内容。这可以通过设置可选end参数来完成,例如;

with open("test", 'w') as f:
    print('Foo1,', file=f, end='')
    print('Foo2,', file=f, end='')
    print('Foo3', file=f)

我建议您使用哪种选择,with因为它使代码更易于阅读。

更新:这种性能差异是由以下事实解释的:write高度缓冲并在实际对磁盘进行任何写操作之前返回(请参阅此答案),而print(可能)使用行缓冲。一个简单的测试就是检查长写的性能,因为行缓冲的缺点(在速度方面)不太明显。

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 + '\n')
end = time.time()

print(end - start, "s")

现在,性能差异变得不那么明显了,的平均时间为2.20s write和3.10s print。如果您需要连接一串字符串来获得这种良好的性能,那么性能会受到影响,因此使用案例中print效率更高的情况很少见。


10

从3.5开始,您还可以使用pathlib

Path.write_text(data, encoding=None, errors=None)

打开以文本模式指向的文件,向其中写入数据,然后关闭文件:

import pathlib

pathlib.Path('textfile.txt').write_text('content')

5

当您说Line时,它表示一些序列化的字符,它们以'\ n'字符结尾。行应该在最后一点,所以我们应该在每行的末尾考虑'\ n'。这是解决方案:

with open('YOURFILE.txt', 'a') as the_file:
    the_file.write("Hello")

在追加模式下,每次写入光标后移至新行,如果要使用w模式,则应\nwrite()函数末尾添加字符:

the_file.write("Hello\n")

1
“在每次写入光标后,在追加模式下移动到新行” –不,不是。
An Se

3

也可以按以下方式使用该io模块:

import io
my_string = "hi there"

with io.open("output_file.txt", mode='w', encoding='utf-8') as f:
    f.write(my_string)

1

可以使用烧瓶中的文件写入文本:

filehandle = open("text.txt", "w")
filebuffer = ["hi","welcome","yes yes welcome"]
filehandle.writelines(filebuffer)
filehandle.close()

0

您也可以尝试 filewriter

pip install filewriter

from filewriter import Writer

Writer(filename='my_file', ext='txt') << ["row 1 hi there", "row 2"]

写入 my_file.txt

接受可迭代对象或带有__str__支持的对象。


0

当我需要写很多新行时,我定义一个使用print函数的lambda :

out = open(file_name, 'w')
fwl = lambda *x, **y: print(*x, **y, file=out) # FileWriteLine
fwl('Hi')

这种方法的好处是可以利用该功能可用的所有print功能。

更新:正如Georgy在评论部分中提到的那样,可以通过以下partial功能进一步改善此想法:

from functools import partial
fwl = partial(print, file=out)

恕我直言,这是一种功能更强,含糊不清的方法。


2
或另一种(可能更干净)的方式编写此代码:from functools import partial; fwl = partial(print, file=out)
乔治,

@Georgy您的方法非常好,可以作为新的答案。
MxNx

1
这个想法与您的想法相同,只是实现略有不同。如果需要,可以将其添加到答案中。我很好
乔治,
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.