用Python读取/写入文件内容的最简单方法


82

在Ruby中,您可以使用读取文件s = File.read(filename)。我在Python中知道的最短和最清楚的是

with open(filename) as f:
    s = f.read()

还有其他方法可以使它更短(最好是一行)并且更具可读性吗?

注意:最初,我将问题表述为“在一行代码中执行此操作”。正如S.Lott所指出的,更短并不一定意味着更具可读性。因此,我改写我的问题只是为了阐明我的意思。我认为Ruby代码更好,更易读,这不一定是因为它是一行还是两行(尽管也很重要),还因为它是一个类方法,而不是实例方法,实例方法对谁关闭文件毫无疑问,如何确保即使引发异常也将其关闭等。如下面的答案所指出的,您可以依靠GC关闭文件(因此使它成为一类文件),但这会使代码更糟虽然更短。不仅因为无法携带,而且使其变得不清楚。


7
创建自己的功能。然后,您可以使用它来获取内容。呼叫将是一条线路。
Felix Kling

1
很好奇,Ruby语句也会关闭文件吗?
dheerosaur

8
-1:没有人在标准高尔夫比赛中获胜。
S.Lott

3
我的问题对我来说很有意义。我试图找到一种更好的方式来编写这两行(with2.5语句之前的4行)。也许有办法,也许没有。我总是可以尝试找出答案,对吧?如果您不喜欢它,请投票并继续前进。:)
ibz

1
这样做的好处File.readlines("filename")是,它以给定的名称读取文件的内容。证据的任何地方都没有文件句柄,描述符或对象。我见过的所有Python“等效项”都包含一个显式的打开/关闭(或更糟糕的是,一个隐式的打开需要一个显式的关闭)。
马克·里德

Answers:


11

如果您愿意使用库,请尝试安装forkd-path(使用easy_install或pip)。

然后,您可以执行以下操作:

from path import path
s = path(filename).bytes()

这个库是一个相当新的库,但是它是一个库的分支,该库已经在Python周围浮动了很多年,并且已经使用了很多。自从几年前我找到这个库以来,我很少使用os.pathopen()更多。


看起来像一个不错的图书馆。我不会仅为此安装它,但我会记住它。
ibz

1
我不明白为什么这是一个可以接受的答案,因为它是完全破解!
nikolay

Windows上的pip 18.6安装的分叉路径v0.2.3与Python 3.6.4不兼容。我当前的python版本似乎不支持八进制常量的格式(例如0777代替0o0777)。
Christoffer Soop '18 -10-9

+1以Eyal Levin的答案。如果8年前我最初回答这个问题时存在pathlib或pathlib2,我会提到它们而不是fork-path。我已经好几年没有使用分叉路径了。
snapshoe


43

与上面相同,但不处理错误:

s = open(filename, 'r').read()

21
不完全是,您的文件保持打开状态。
ibz

3
当引用计数为零时,CPython实现确实关闭文件,但这是不应依赖的实现细节。
Mark Tolonen's

1
这确实可以处理错误;异常将照常引发。这并没有“离开文件打开”,但它可能做的是事业要在文件关闭延迟取决于GC执行。这可能是个问题(在Windows中锁定,例如,如果循环访问多个文件,则为FD限制),但这与保持打开状态(例如,泄漏文件)大不相同。
格伦·梅纳德

11
如果您的设计目标是“一行代码”,则说明您吸入了过多的Perl,并且需要安排一些认真的工作。
格伦·梅纳德

6
不,丝毫不会混淆。
格伦·梅纳德

36

使用pathlib

Python 3.5及更高版本:

from pathlib import Path
contents = Path(file_path).read_text()

对于较低版本的Python,请使用pathlib2

$ pip install pathlib2

然后

from pathlib2 import Path
contents = Path(file_path).read_text()

写作同样简单:

Path(file_path).write_text('my text')

18
contents = open(filename).read()

9
以及何时关闭文件?
ibz

1
@ionut bizau-我想当归还open(...)垃圾时。如果我错了,请有人纠正我。
2010年

1
这是最短的方法。我不知道为什么它没有选票。
Pritesh Acharya

10

这不是Perl;您不想将价值多行的代码强制装配到一行上。编写一个函数,然后调用该函数需要一行代码。

def read_file(fn):
    """
    >>> import os
    >>> fn = "/tmp/testfile.%i" % os.getpid()
    >>> open(fn, "w+").write("testing")
    >>> read_file(fn)
    'testing'
    >>> os.unlink(fn)
    >>> read_file("/nonexistant")
    Traceback (most recent call last):
        ...
    IOError: [Errno 2] No such file or directory: '/nonexistant'
    """
    with open(fn) as f:
        return f.read()

if __name__ == "__main__":
    import doctest
    doctest.testmod()

5

速度慢,丑陋,特定于平台...但是只有一线;-)

import subprocess

contents = subprocess.Popen('cat %s' % filename, shell = True, stdout = subprocess.PIPE).communicate()[0]

3
啊!(超出“ a”以达到最小字符限制)
Peter Gibson

5
当然符合这个问题的精神……不正确地使用Python以使其类似于Bash并不比使其类似于Ruby或Perl更糟。
2010年

3

像这样简单:

    f=open('myfile.txt')
    s=f.read()
    f.close()

并随心所欲地处理内容“ s”


-1
contents = open(filename)

这为您提供了生成器,因此您必须将值保存在某个地方,或者

contents = [line for line in open(filename)]

这样就不可能保存到列表中的明确关闭(至少根据我的Python知识)。


1
并且内容=''.join(open(filename)中的行的行),您拥有原始文件的内容...
eumiro 2010年

使用文件作为迭代器无法关闭文件确定性(像with这样)。不能这样,因为在迭代完成之后,查找文件并再次开始读取仍然有效,如果迭代关闭了该文件,则该方法将无效。
格伦·梅纳德

@Glenn但是,如果像我的示例那样在列表理解中使用生成器,由于它没有名称,甚至无法关闭它。
Tony Veijalainen'9

“不能够关闭它”是一样的“不需要关闭它。”
格伦·梅纳德

也许是这样,但是您不知道如何从列表理解内部访问该文件句柄。应该在Python中执行“完成所有文件的I / O,关闭所有程序打开的文件”命令吗?还是文件对象的显式gc就足够了?文件句柄超出了范围,因为列表理解是单独的范围。
Tony Veijalainen 2010年
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.