如何在Python中读取文件的每一行,并将每一行存储为列表中的元素?
我想逐行读取文件,并将每一行附加到列表的末尾。
如何在Python中读取文件的每一行,并将每一行存储为列表中的元素?
我想逐行读取文件,并将每一行附加到列表的末尾。
当前回答
最简单的方法
一个简单的方法是:
将整个文件作为字符串读取逐行拆分字符串
在一行中,这将给出:
lines = open('C:/path/file.txt').read().splitlines()
然而,这是一种非常低效的方式,因为这将在内存中存储两个版本的内容(对于小文件来说可能不是大问题,但仍然如此)。[谢谢Mark Amery]。
有两种更简单的方法:
将文件用作迭代器
lines = list(open('C:/path/file.txt'))
# ... or if you want to have a list without EOL characters
lines = [l.rstrip() for l in open('C:/path/file.txt')]
如果您使用的是Python 3.4或更高版本,最好使用pathlib为文件创建一个路径,该路径可以用于程序中的其他操作:
from pathlib import Path
file_path = Path("C:/path/file.txt")
lines = file_path.read_text().split_lines()
# ... or ...
lines = [l.rstrip() for l in file_path.open()]
其他回答
要将文件读取到列表中,需要执行以下三项操作:
打开文件读取文件将内容存储为列表
幸运的是,Python非常容易做到这些,所以将文件读入列表的最短方法是:
lst = list(open(filename))
不过,我会补充一些解释。
打开文件
我假设您想打开一个特定的文件,而不直接处理文件句柄(或类似文件的句柄)。Python中最常用的打开文件的函数是open,在Python 2.7中它需要一个强制参数和两个可选参数:
文件名模式缓冲(我将忽略这个答案中的这个参数)
文件名应该是表示文件路径的字符串。例如:
open('afile') # opens the file named afile in the current working directory
open('adir/afile') # relative path (relative to the current working directory)
open('C:/users/aname/afile') # absolute path (windows)
open('/usr/local/afile') # absolute path (linux)
请注意,需要指定文件扩展名。这对于Windows用户尤其重要,因为在浏览器中查看时,默认情况下,.txt或.doc等文件扩展名是隐藏的。
第二个参数是mode,默认为r,表示“只读”。这正是你需要的。
但如果你真的想要创建一个文件和/或写入一个文件,你需要一个不同的参数。如果你想要一个概览,有一个很好的答案。
对于读取文件,可以省略模式或显式传入:
open(filename)
open(filename, 'r')
两者都将以只读模式打开文件。如果您想在Windows上读取二进制文件,则需要使用模式rb:
open(filename, 'rb')
在其他平台上,“b”(二进制模式)被简单地忽略。
既然我已经演示了如何打开该文件,那么让我们来谈谈您总是需要再次关闭它的事实。否则,它将保持文件的打开文件句柄,直到进程退出(或Python破坏文件句柄)。
虽然您可以使用:
f = open(filename)
# ... do stuff with f
f.close()
当打开和关闭之间发生异常时,将无法关闭文件。您可以通过尝试并最终:
f = open(filename)
# nothing in between!
try:
# do stuff with f
finally:
f.close()
然而,Python提供的上下文管理器具有更漂亮的语法(但对于open,它几乎与上面的try和finally相同):
with open(filename) as f:
# do stuff with f
# The file is always closed after the with-scope ends.
最后一种方法是用Python打开文件的推荐方法!
正在读取文件
好的,你已经打开了文件,现在如何阅读?
open函数返回一个文件对象,它支持Pythons迭代协议。每次迭代都会给你一行:
with open(filename) as f:
for line in f:
print(line)
这将打印文件的每一行。但是,请注意,每一行结尾都将包含一个换行符(您可能需要检查Python是否具有通用换行符支持,否则您也可以在Windows或Mac上使用换行符)。如果您不想这样做,可以简单地删除最后一个字符(或Windows上的最后两个字符):
with open(filename) as f:
for line in f:
print(line[:-1])
但最后一行不一定有换行符,所以不应该使用它。可以检查它是否以尾随换行符结尾,如果是,请将其删除:
with open(filename) as f:
for line in f:
if line.endswith('\n'):
line = line[:-1]
print(line)
但是您可以简单地删除字符串末尾的所有空格(包括字符),这也会删除所有其他尾随空格,因此如果这些空格很重要,您必须小心:
with open(filename) as f:
for line in f:
print(f.rstrip())
但是,如果行以\r\n(Windows“newlines”)结尾,.rstrip()也会处理\r!
将内容存储为列表
既然您知道了如何打开文件并读取它,现在是将内容存储在列表中的时候了。最简单的选择是使用list函数:
with open(filename) as f:
lst = list(f)
如果你想去掉后面的换行符,你可以使用列表理解:
with open(filename) as f:
lst = [line.rstrip() for line in f]
或者更简单:默认情况下,file对象的.readlines()方法返回一个行列表:
with open(filename) as f:
lst = f.readlines()
这还将包括后面的换行符,如果你不想要它们,我建议使用[line.rstrip()for line-in-f]方法,因为它避免了在内存中保留包含所有行的两个列表。
有一个额外的选项可以获得所需的输出,但它相当“次优”:读取字符串中的完整文件,然后在换行符上拆分:
with open(filename) as f:
lst = f.read().split('\n')
or:
with open(filename) as f:
lst = f.read().splitlines()
因为不包含拆分字符,所以它们会自动处理尾随换行符。然而,它们并不理想,因为您将文件保存为字符串和内存中的行列表!
总结
在打开文件时使用with open(…)作为f,因为您不需要自己关闭文件,即使发生异常,它也会关闭文件。文件对象支持迭代协议,因此逐行读取文件与file_object:中的行一样简单。始终浏览文档以查找可用的函数/类。大多数时候,这项任务有一个完美的匹配,或者至少有一两个好的匹配。在这种情况下,明显的选择是readlines(),但如果您想在将行存储在列表中之前处理它们,我建议您进行简单的列表理解。
最简单的方法是:
lines = list(open('filename'))
or
lines = tuple(open('filename'))
or
lines = set(open('filename'))
在set的情况下,我们必须记住,我们没有保留行顺序,并删除重复的行。
下面我添加了@MarkAmery的一个重要补充:
由于您既没有在文件对象上调用.close,也没有使用with语句,因此在某些Python实现中,文件在读取后可能不会关闭,您的进程将泄漏打开的文件句柄。在CPython(大多数人使用的普通Python实现)中,这不是问题,因为文件对象将立即被垃圾收集,这将关闭文件,但通常认为最好的做法是:
with open('filename') as f: lines = list(f)
以确保无论您使用的是什么Python实现,文件都会被关闭。
大纲和摘要
使用文件名,从Path(filename)对象处理文件,或直接将open(filename)作为f,执行以下操作之一:
列表(fileinput.input(文件名))使用path.open()作为f,调用f.readlines()列表(f)path.read_text().splitline()path.read_text().splitlines(keepends=True)迭代fileinput.input或f和list.append每行一次将f传递给绑定的list.extend方法在列表理解中使用f
我将在下面解释每一个的用例。
在Python中,如何逐行读取文件?
这是一个很好的问题。首先,让我们创建一些示例数据:
from pathlib import Path
Path('filename').write_text('foo\nbar\nbaz')
文件对象是惰性迭代器,所以只需对其进行迭代。
filename = 'filename'
with open(filename) as f:
for line in f:
line # do something with the line
或者,如果您有多个文件,请使用另一个惰性迭代器fileinput.input。只有一个文件:
import fileinput
for line in fileinput.input(filename):
line # process the line
或者对于多个文件,向其传递文件名列表:
for line in fileinput.input([filename]*2):
line # process the line
同样,上面的f和fileinput.input都是/return惰性迭代器。您只能使用一次迭代器,因此为了在提供函数代码的同时避免冗长,我将在此处使用稍微简洁的fileinput.input(文件名)。
在Python中,如何将文件逐行读入列表?
啊,但出于某种原因,你想把它列在列表中?如果可能的话,我会避免。但如果你坚持。。。只需将fileinput.input(文件名)的结果传递给列表:
list(fileinput.input(filename))
另一个直接的答案是调用f.readlines,它返回文件的内容(最多为可选的提示字符数,因此您可以这样将其分解为多个列表)。
您可以通过两种方式访问此文件对象。一种方法是将文件名传递给打开的内置程序:
filename = 'filename'
with open(filename) as f:
f.readlines()
或者使用pathlib模块中的新Path对象(我已经非常喜欢它,并将从这里开始使用):
from pathlib import Path
path = Path(filename)
with path.open() as f:
f.readlines()
list还将使用文件迭代器并返回一个列表-这也是一个非常直接的方法:
with path.open() as f:
list(f)
如果您不介意在拆分之前将整个文本作为一个字符串读入内存,那么可以使用Path对象和splitlines()字符串方法将其作为一行代码。默认情况下,拆分线会删除换行符:
path.read_text().splitlines()
如果要保留换行符,请传递keepends=True:
path.read_text().splitlines(keepends=True)
我想逐行读取文件,并将每一行附加到列表的末尾。
现在,考虑到我们已经用几种方法轻松地演示了最终结果,这一要求有点愚蠢。但在列出列表时,您可能需要对行进行筛选或操作,所以让我们来幽默一下这个请求。
使用list.append可以在附加每一行之前对其进行筛选或操作:
line_list = []
for line in fileinput.input(filename):
line_list.append(line)
line_list
使用list.extend会更直接一些,如果您有一个预先存在的列表,可能会有用:
line_list = []
line_list.extend(fileinput.input(filename))
line_list
或者更惯用地说,我们可以使用列表理解,并根据需要在其中进行映射和过滤:
[line for line in fileinput.input(filename)]
或者更直接地,要关闭圆,只需将其传递到列表即可直接创建新列表,而无需对行进行操作:
list(fileinput.input(filename))
结论
您已经看到了许多将文件中的行放入列表的方法,但我建议您避免将大量数据具体化到列表中,而是尽可能使用Python的惰性迭代来处理数据。
也就是说,首选fileinput.input或path.open()作为f。
使用Python 2和Python 3读写文本文件;它适用于Unicode
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Define data
lines = [' A first string ',
'A Unicode sample: €',
'German: äöüß']
# Write text file
with open('file.txt', 'w') as fp:
fp.write('\n'.join(lines))
# Read text file
with open('file.txt', 'r') as fp:
read_lines = fp.readlines()
read_lines = [line.rstrip('\n') for line in read_lines]
print(lines == read_lines)
注意事项:
with是所谓的上下文管理器。它确保打开的文件再次关闭。这里的所有解决方案,只要简单地生成.strip()或.rstrip(),就无法再现线条,因为它们也会剥离空白。
常用文件结尾
.txt
更高级的文件写入/读取
CSV:超简单格式(读写)JSON:适合编写人类可读数据;非常常用(读写)YAML:YAML是JSON的超集,但更易于阅读(读写,JSON和YAML的比较)pickle:Python序列化格式(读写)MessagePack(Python包):更紧凑的表示(读写)HDF5(Python包):适合矩阵(读写)XML:也存在*叹息*(读写)
对于您的应用程序,以下内容可能很重要:
其他编程语言的支持读/写性能紧凑性(文件大小)
另请参阅:数据序列化格式的比较
如果您正在寻找创建配置文件的方法,您可能需要阅读我的Python配置文件短文。
下面是我用来简化文件I/O的Python(3)助手库类:
import os
# handle files using a callback method, prevents repetition
def _FileIO__file_handler(file_path, mode, callback = lambda f: None):
f = open(file_path, mode)
try:
return callback(f)
except Exception as e:
raise IOError("Failed to %s file" % ["write to", "read from"][mode.lower() in "r rb r+".split(" ")])
finally:
f.close()
class FileIO:
# return the contents of a file
def read(file_path, mode = "r"):
return __file_handler(file_path, mode, lambda rf: rf.read())
# get the lines of a file
def lines(file_path, mode = "r", filter_fn = lambda line: len(line) > 0):
return [line for line in FileIO.read(file_path, mode).strip().split("\n") if filter_fn(line)]
# create or update a file (NOTE: can also be used to replace a file's original content)
def write(file_path, new_content, mode = "w"):
return __file_handler(file_path, mode, lambda wf: wf.write(new_content))
# delete a file (if it exists)
def delete(file_path):
return os.remove() if os.path.isfile(file_path) else None
然后使用FileIO.lines函数,如下所示:
file_ext_lines = FileIO.lines("./path/to/file.ext"):
for i, line in enumerate(file_ext_lines):
print("Line {}: {}".format(i + 1, line))
请记住,mode(默认为“r”)和filter_fn(默认为检查空行)参数是可选的。
您甚至可以删除read、write和delete方法,只保留FileIO.line,甚至将其转换为一个单独的方法read_lines。