正确的写行到文件的方法?

时间:2011-05-28 05:44:54

标签: python file-io

我习惯做print >>f, "hi there"

但是,print >>似乎已被弃用。上面这一行的推荐方法是什么?

更新的: 关于"\n"的所有答案......是普遍的还是特定于Unix的? IE,我应该在Windows上进行"\r\n"吗?

16 个答案:

答案 0 :(得分:936)

您应该使用自Python 2.6 +

以来可用的print()函数
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 documentation有关换行符的信息:

  

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

答案 1 :(得分:897)

这应该简单如下:

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

来自文档:

  

在编写以文本模式打开的文件时,不要使用os.linesep作为行终止符(默认值);在所有平台上使用单个'\ n'。

一些有用的阅读:

答案 2 :(得分:105)

python docs推荐这种方式:

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

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

来自docs.python.org的声明:

  

在处理文件时,最好使用'和'关键字   对象。这样做的好处是文件在之后正确关闭   即使在途中出现异常,它的套件也会完成。它是   也比编写等效的try-finally块短得多。

答案 3 :(得分:85)

关于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确实 NOT 产生与'\n'相同的结果。它无法产生相同的结果。 'hi there' + os.linesep相当于'hi there\r\n' NOT 等同于'hi there\n'

就是这么简单:使用\n将自动转换为os.linesep。从Python的第一个端口到Windows,它就变得非常简单。

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

请勿使用os.linesep!

答案 4 :(得分:52)

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

我会用:

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

在记忆中Tim Toady

答案 5 :(得分:20)

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

from __future__ import print_function

然后你做

print("hi there", file=f)

答案 6 :(得分:16)

如果您正在编写大量数据并且速度是一个问题,那么您应该使用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在我的机器上以2.45秒完成,而print花了大约4倍(9.76秒)。话虽如此,在大多数现实世界的情景中,这都不是问题。

如果您选择使用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高度缓冲并在实际发生磁盘写入之前返回(参见this answer),而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")

性能差异现在变得不那么明显,write的平均时间为2.20秒,print的平均时间为3.10秒。如果你需要连接一堆字符串来使这个loooong行性能受到影响,那么print效率更高的用例有点罕见。

答案 7 :(得分:8)

从3.5开始,您也可以为此使用pathlib

  

Path.write_text(数据,编码=无,错误=无)

     

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

import pathlib

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

答案 8 :(得分:4)

当你说Line时它意味着一些序列化的字符,这些字符以'\ n'字符结尾。线应该在某个时刻持续,所以我们应该在每一行的末尾考虑'\ n'。这是解决方案:

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

在每次写入后的追加模式中光标移动到新行,如果你想使用'w'模式,你应该在write()函数的末尾添加'\ n'个字符:

the_file.write('Hello'+'\n')

答案 9 :(得分: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)

答案 10 :(得分:1)

如果您想在列表中插入每行格式的项目,一种开始方式可能是:

with open('somefile.txt', 'a') as the_file:
for item in python_list_of_strings:
    the_file.write(f"{item}\n")

答案 11 :(得分: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__的可迭代对象或对象。

答案 12 :(得分: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)

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

答案 13 :(得分:0)

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

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

答案 14 :(得分:0)

如果要避免使用write()writelines()并自己将字符串与换行符连接,则可以将所有行传递到print()以及换行符分隔符和文件中作为关键字参数处理。此代码段假定您的字符串没有尾随换行符。

print(line1, line2, sep="\n", file=f)

您不需要在末尾添加特殊的换行符,因为print()可以帮您实现这一点。

如果列表中有任意行,则可以使用列表扩展将它们全部传递给print()

lines = ["The Quick Brown Fox", "Lorem Ipsum"]
print(*lines, sep="\n", file=f)

在Windows上可以使用"\n"作为分隔符,因为print()还将自动将其转换为Windows CRLF换行符("\r\n")。

答案 15 :(得分:0)

由于其他人已经回答了如何做,所以我将逐行回答它的发生情况。

with FileOpenerCM('file.txt') as fp: # is equal to "with open('file.txt') as fp:"
      fp.write('dummy text')

这是所谓的context managerwith块附带的任何内容都是上下文管理器。让我们看看它是如何发生的。

class FileOpenerCM:
     def __init__(self, file, mode='w'):
         self.file = open(file, mode)
      
     def __enter__(self):
          return self.file
      
     def __exit__(self, exc_type, exc_value, exc_traceback):
         self.file.close()

第一个方法__init__是(众所周知)对象的初始化方法。每当创建对象obj.__init__时,都必须调用它。这就是您放置所有init类代码的地方。

第二种方法__enter__有点有趣。你们中的有些人可能没有看到它,因为它是上下文管理器的特定方法。它返回的是在as关键字之后要分配给变量的值。在我们的情况下为fp

最后一个方法是捕获错误或代码退出with块后运行的方法。 exc_typeexc_valueexc_traceback变量是保存在block内部发生的错误的值的变量。例如,

exc_type: TypeError
exc_value: unsupported operand type(s) for +: 'int' and 'str
exc_traceback: <traceback object at 0x6af8ee10bc4d>

从前两个变量中,您可以获得有关错误的足够信息。老实说,我不知道第三个变量的用法,但是对我来说,前两个就足够了。如果您确实想对上下文管理器进行更多研究,则可以这样做,并请注意,编写类并不是编写上下文管理器的唯一方法。使用contextlib,您还可以通过函数(实际上是生成器)编写上下文管理器。完全由您决定。你一定可以尝试 生成器函数与contextlib一起使用,但我认为类更整洁。