如何将文件逐行读取到列表中?

如何在Python中读取文件的每一行并将每一行存储为列表中的元素?

我想逐行读取文件并将每一行附加到列表的末尾。

4592881 次浏览

这将从文件中产生一个行的“数组”。

lines = tuple(open(filename, 'r'))

open返回一个可以迭代的文件。当您迭代一个文件时,您可以从该文件中获取行。tuple可以获取一个迭代器并从您给它的迭代器中实例化一个元组实例。lines是从文件的行创建的元组。

这比必要的更明确,但做你想要的。

with open("file.txt") as file_in:lines = []for line in file_in:lines.append(line)

输入与输出

with open('filename') as f:lines = f.readlines()

或者剥离换行符:

with open('filename') as f:lines = [line.rstrip('\n') for line in f]

这段代码将把整个文件读入内存,并删除每行末尾的所有空格字符(换行符和空格):

with open(filename) as file:lines = [line.rstrip() for line in file]

如果你正在处理一个大文件,那么你应该逐行读取和处理它:

with open(filename) as file:for line in file:print(line.rstrip())

在Python 3.8及更高版本中,您可以使用海象操作员的这时循环,如下所示:

with open(filename) as file:while (line := file.readline().rstrip()):print(line)

根据您计划对文件执行的操作以及它的编码方式,您可能还需要手动设置访问模式和字符编码:

with open(filename, 'r', encoding='UTF-8') as file:while (line := file.readline().rstrip()):print(line)

另一个选项是#0,例如:

import numpy as npdata = np.genfromtxt("yourfile.dat",delimiter="\n")

这将使data成为一个NumPy数组,其行数与文件中的行数一样多。

如果您想从命令行或标准输入读取文件,您还可以使用fileinput模块:

# reader.pyimport fileinput
content = []for line in fileinput.input():content.append(line.strip())
fileinput.close()

像这样将文件传递给它:

$ python reader.py textfile.txt

阅读更多:http://docs.python.org/2/library/fileinput.html

f = open("your_file.txt",'r')out = f.readlines() # will append in the list out

现在变量out是你想要的列表(数组)。你可以这样做:

for line in out:print (line)

或:

for line in f:print (line)

你会得到同样的结果。

如果您希望包含\n

with open(fname) as f:content = f.readlines()

如果您不希望包含\n

with open(fname) as f:content = f.read().splitlines()

这里还有一个选项,通过对文件使用列表推导;

lines = [line.rstrip() for line in open('file.txt')]

这应该是更有效的方式,因为大部分工作都是在Python解释器中完成的。

将文件的行读取到列表中的干净和Pythonic方式


首先,您应该专注于打开文件并以高效和Pythonic的方式阅读其内容。这是我个人不喜欢的方式的一个例子:

infile = open('my_file.txt', 'r')  # Open the file for reading.
data = infile.read()  # Read the contents of the file.
infile.close()  # Close the file since we're done using it.

相反,我更喜欢下面的方法来打开文件进行读写非常干净,不需要额外的关闭文件步骤一旦您完成使用它。在下面的声明中,我们正在打开文件用于读取,并将其分配给变量'infile'。此语句已运行完毕,文件将自动关闭。

# Open the file for reading.with open('my_file.txt', 'r') as infile:
data = infile.read()  # Read the contents of the file into memory.

现在我们需要专注于将这些数据放入python列表中,因为它们可迭代、高效和灵活。在您的情况下,所需的目标是将文本文件的每一行放入一个单独的元素中。为此,我们将使用拆分线方法,如下所示:

# Return a list of the lines, breaking at line boundaries.my_list = data.splitlines()

最终产品:

# Open the file for reading.with open('my_file.txt', 'r') as infile:
data = infile.read()  # Read the contents of the file into memory.
# Return a list of the lines, breaking at line boundaries.my_list = data.splitlines()

测试我们的代码:

  • 文本文件的内容:
     A fost odatã ca-n povesti,A fost ca niciodatã,Din rude mãri împãrãtesti,O prea frumoasã fatã.
  • 出于测试目的打印语句:
    print my_list  # Print the list.
# Print each line in the list.for line in my_list:print line
# Print the fourth element in this list.print my_list[3]
  • 输出(由于Unicode字符,外观不同):
     ['A fost odat\xc3\xa3 ca-n povesti,', 'A fost ca niciodat\xc3\xa3,','Din rude m\xc3\xa3ri \xc3\xaemp\xc3\xa3r\xc3\xa3testi,', 'O preafrumoas\xc3\xa3 fat\xc3\xa3.']
A fost odatã ca-n povesti, A fost ca niciodatã, Din rude mãriîmpãrãtesti, O prea frumoasã fatã.
O prea frumoasã fatã.

最简单的方法就是

一个简单的方法是:

  1. 将整个文件作为字符串读取
  2. 逐行拆分字符串

在一行中,这将给出:

lines = open('C:/path/file.txt').read().splitlines()

然而,这是一种非常低效的方式,因为这将在内存中存储2个版本的内容(对于小文件来说可能不是一个大问题,但仍然)。[感谢马克·阿梅里]。

有两种更简单的方法:

  1. 使用文件作为迭代器
lines = list(open('C:/path/file.txt'))# ... or if you want to have a list without EOL characterslines = [l.rstrip() for l in open('C:/path/file.txt')]
  1. 如果您使用的是Python 3.4或更高版本,最好使用pathlib为您的文件创建一个路径,您可以将其用于程序中的其他操作:
from pathlib import Pathfile_path = Path("C:/path/file.txt")lines = file_path.read_text().split_lines()# ... or ...lines = [l.rstrip() for l in file_path.open()]

根据Python的文件对象的方法,将文本文件转换为list的最简单方法是:

with open('file.txt') as f:my_list = list(f)# my_list = [x.rstrip() for x in f] # remove line breaks

如果您只需要遍历文本文件行,您可以使用:

with open('file.txt') as f:for line in f:...

老答案:

使用withreadlines()

with open('file.txt') as f:lines = f.readlines()

如果您不关心关闭文件,则此单行代码将起作用:

lines = open('file.txt').readlines()

传统方式:

f = open('file.txt') # Open file on read modelines = f.read().splitlines() # List with stripped line-breaksf.close() # Close file

您还可以在NumPy中使用loadtxt命令。这比genFromtxt检查更少的条件,所以它可能更快。

import numpydata = numpy.loadtxt(filename, delimiter="\n")

您可以简单地按照建议执行以下操作:

with open('/your/path/file') as f:my_lines = f.readlines()

请注意,这种方法有两个缺点:

1)您将所有行存储在内存中。在一般情况下,这是一个非常糟糕的主意。文件可能非常大,您可能会运行内存溢出。即使它不大,也只是浪费内存。

2)这不允许在阅读时处理每一行。因此,如果在此之后处理您的行,则效率不高(需要两次而不是一次)。

一般情况下的更好方法如下:

with open('/your/path/file') as f:for line in f:process(line)

您可以在其中以任何您想要的方式定义流程函数。例如:

def process(line):if 'save the world' in line.lower():superman.save_the_world()

Superman类的实现留给你做练习)。

这对于任何文件大小都可以很好地工作,并且您只需1次就可以浏览您的文件。这通常是通用解析器的工作方式。

使用这个:

import pandas as pddata = pd.read_csv(filename) # You can also add parameters such as header, sep, etc.array = data.values

data是一种数据帧类型,使用值来获取ndarray。您也可以使用array.tolist()获取列表。

只需使用拆分线()函数。这是一个示例。

inp = "file.txt"data = open(inp)dat = data.read()lst = dat.splitlines()print lst# print(lst) # for python 3

在输出中,您将获得行列表。

如果你面对非常大/巨大的文件并且想要阅读更快(假设你在TopCoderHackerRank编码竞赛中),你可能会一次将相当大的行块读取到内存缓冲区中,而不仅仅是在文件级别逐行迭代。

buffersize = 2**16with open(path) as f:while True:lines_buffer = f.readlines(buffersize)if not lines_buffer:breakfor line in lines_buffer:process(line)

具有文本文件内容:

line 1line 2line 3

我们可以在上面txt的同一个目录中使用这个Python脚本

>>> with open("myfile.txt", encoding="utf-8") as file:...     x = [l.rstrip("\n") for l in file]>>> x['line 1','line 2','line 3']

使用append:

x = []with open("myfile.txt") as file:for l in file:x.append(l.strip())

或:

>>> x = open("myfile.txt").read().splitlines()>>> x['line 1', 'line 2', 'line 3']

或:

>>> x = open("myfile.txt").readlines()>>> x['linea 1\n', 'line 2\n', 'line 3\n']

或:

def print_output(lines_in_textfile):print("lines_in_textfile =", lines_in_textfile)
y = [x.rstrip() for x in open("001.txt")]print_output(y)
with open('001.txt', 'r', encoding='utf-8') as file:file = file.read().splitlines()print_output(file)
with open('001.txt', 'r', encoding='utf-8') as file:file = [x.rstrip("\n") for x in file]print_output(file)

输出:

lines_in_textfile = ['line 1', 'line 2', 'line 3']lines_in_textfile = ['line 1', 'line 2', 'line 3']lines_in_textfile = ['line 1', 'line 2', 'line 3']

命令行版本

#!/bin/python3import osimport sysabspath = os.path.abspath(__file__)dname = os.path.dirname(abspath)filename = dname + sys.argv[1]arr = open(filename).read().split("\n")print(arr)

运行:

python3 somefile.py input_file_name.txt

使用Python 2和Python 3读写文本文件;它适用于Unicode

#!/usr/bin/env python3# -*- coding: utf-8 -*-
# Define datalines = ['     A first string  ','A Unicode sample: €','German: äöüß']
# Write text filewith open('file.txt', 'w') as fp:fp.write('\n'.join(lines))
# Read text filewith 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()将无法再现lines,因为它们也剥离了空白。

常见文件结尾

.txt

更高级的文件写入/读取

对于您的应用程序,以下内容可能很重要:

  • 支持其他编程语言
  • 读/写性能
  • 紧凑性(文件大小)

另见:数据序列化格式的比较

如果您正在寻找一种创建配置文件的方法,您可能想阅读我的短文Python中的配置文件

要将文件读取到列表中,您需要做三件事:

  • 打开文件
  • 读一下档案
  • 将内容存储为列表

幸运的是,Python使这些事情变得非常容易,因此将文件读取到列表中的最短方法是:

lst = list(open(filename))

但我会补充一些解释。

打开文件

我假设你想打开一个特定的文件,并且你不直接处理文件句柄(或类似文件的句柄)。在Python中打开文件最常用的函数是#0,它需要一个强制性参数和两个可选参数在Python 2.7中:

  • 文件名
  • 模式
  • 缓冲(我将在这个答案中忽略这个参数)

文件名应该是代表文件的路径的字符串。例如:

open('afile')   # opens the file named afile in the current working directoryopen('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,表示“只读”。这正是您在案例中需要的。

但是如果你真的想创建一个文件和/或写入一个文件,你需要一个不同的参数。有一个很好的答案如果你想要一个概述

要读取文件,您可以省略mode或显式传入:

open(filename)open(filename, 'r')

两者都将以只读模式打开文件。如果您想在Windows上读取二进制文件,您需要使用模式rb

open(filename, 'rb')

在其他平台上,'b'(二进制模式)被简单地忽略。


现在我已经展示了如何open文件,让我们谈谈你总是需要再次close它的事实。否则它将保持文件的打开文件句柄,直到进程退出(或Python丢弃文件句柄)。

虽然您可以使用:

f = open(filename)# ... do stuff with ff.close()

openclose之间的内容抛出异常时,这将无法关闭文件。您可以使用tryfinally来避免这种情况:

f = open(filename)# nothing in between!try:# do stuff with ffinally:f.close()

然而,Python提供了具有更漂亮语法的上下文管理器(但对于open,它几乎与上面的tryfinally相同):

with open(filename) as f:# do stuff with f# The file is always closed after the with-scope ends.

最后一种方法是在Python中打开文件的建议方法!

读取文件

好的,你已经打开了文件,现在如何阅读它?

open函数返回一个#1对象,它支持Pythons迭代协议。每次迭代都会给你一行:

with open(filename) as f:for line in f:print(line)

这将打印文件的每一行。但是请注意,每行将在末尾包含一个换行符\n(您可能需要检查您的Python是否使用通用换行符支持构建-否则您也可以将Windows上的\r\n或Mac上的\r作为换行符)。如果您不希望,您可以简单地删除最后一个字符(或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)

但是你可以简单地从字符串的末尾中删除所有空格(包括\n字符),这也将删除所有其他尾随空格,所以如果这些很重要,你必须小心:

with open(filename) as f:for line in f:print(f.rstrip())

但是,如果行以\r\n(Windows“换行符”)结尾,则.rstrip()也将处理\r

将内容存储为列表

现在您知道如何打开文件并读取它,是时候将内容存储在列表中了。最简单的选择是使用#0函数:

with open(filename) as f:lst = list(f)

如果你想去掉尾随的换行符,你可以使用列表理解代替:

with open(filename) as f:lst = [line.rstrip() for line in f]

或者更简单:file对象的#0方法默认返回list行:

with open(filename) as f:lst = f.readlines()

这也将包括尾随的换行符,如果你不想要它们,我会推荐[line.rstrip() for line in f]方法,因为它避免了在内存中保留两个包含所有行的列表。

还有一个额外的选项可以获得所需的输出,但它相当“次优”:#0字符串中的完整文件,然后在换行符上拆分:

with open(filename) as f:lst = f.read().split('\n')

或:

with open(filename) as f:lst = f.read().splitlines()

这些自动处理尾随的换行符,因为不包括split字符。然而,它们并不理想,因为您将文件保留为字符串和内存中的行列表!

总结

  • 打开文件时使用with open(...) as f,因为您不需要自己关闭文件,即使发生异常,它也会关闭文件。
  • file对象支持迭代协议,因此逐行读取文件就像for line in the_file_object:一样简单。
  • 始终浏览可用函数/类的留档。大多数时候,任务或至少有一两个好的匹配。在这种情况下,显而易见的选择是readlines(),但如果您想在将行存储在列表中之前处理它们,我建议使用简单的列表理解。

我喜欢用下面的方法。立即读台词。

contents = []for line in open(filepath, 'r').readlines():contents.append(line.strip())

或者使用列表理解:

contents = [line.strip() for line in open(filepath, 'r').readlines()]

在Python 3.4中引入,#0有一个非常方便的方法来从文件中读取文本,如下所示:

from pathlib import Pathp = Path('my_text_file')lines = p.read_text().splitlines()

splitlines调用将它从包含文件全部内容的字符串转换为文件中的行列表。)

pathlib有很多方便的地方。#1简洁明了,你不必担心打开和关闭文件。如果你需要做的就是一次性读完文件,这是一个不错的选择。

大纲和总结

使用filename,从Path(filename)对象处理文件,或直接使用open(filename) as f,执行以下操作之一:

  • list(fileinput.input(filename))
  • 使用with path.open() as f,调用f.readlines()
  • list(f)
  • path.read_text().splitlines()
  • path.read_text().splitlines(keepends=True)
  • 每次迭代fileinput.inputflist.append的每一行
  • f传递给绑定的list.extend方法
  • 在列表理解中使用f

我在下面解释每个用例。

在Python中,我如何逐行读取文件?

这是一个很好的问题。首先,让我们创建一些示例数据:

from pathlib import PathPath('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

同样,上面的ffileinput.input都是/返回惰性迭代器。你只能使用一次迭代器,所以为了提供函数式代码,同时避免冗长,我将从这里使用稍微简洁的fileinput.input(filename)

在Python中,我如何逐行读取文件到一个列表?

啊,但是你出于某种原因想要它在列表中?如果可能的话,我会避免这样做。但是如果你坚持……只需将fileinput.input(filename)的结果传递给list

list(fileinput.input(filename))

另一个直接的答案是调用f.readlines,它返回文件的内容(最多可选择hint个字符,因此您可以以这种方式将其分解为多个列表)。

您可以通过两种方式访问此文件对象。一种方法是将文件名传递给open内置:

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()字符串方法作为单行代码执行此操作。默认情况下,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即可直接创建一个新列表,而无需对行进行操作:

list(fileinput.input(filename))

结论

您已经看到了许多将文件中的行转换为列表的方法,但我建议您避免将大量数据具体化到列表中,而是尽可能使用Python的懒惰迭代来处理数据。

也就是说,更喜欢fileinput.inputwith path.open() as f

我会尝试下面提到的方法之一。我使用的示例文件的名称为dummy.txt。您可以找到文件这里。我假设该文件与代码位于同一目录中(您可以更改fpath以包含正确的文件名和文件夹路径)。

在下面提到的两个示例中,您想要的列表由lst给出。

1.第一种方法

fpath = 'dummy.txt'with open(fpath, "r") as f: lst = [line.rstrip('\n \t') for line in f]
print lst>>>['THIS IS LINE1.', 'THIS IS LINE2.', 'THIS IS LINE3.', 'THIS IS LINE4.']

2.在第二种方法中,可以使用csv.reader模块从Python标准库

import csvfpath = 'dummy.txt'with open(fpath) as csv_file:csv_reader = csv.reader(csv_file, delimiter='   ')lst = [row[0] for row in csv_reader]
print lst>>>['THIS IS LINE1.', 'THIS IS LINE2.', 'THIS IS LINE3.', 'THIS IS LINE4.']

您可以使用这两种方法中的任何一种。这两种方法创建lst所花费的时间几乎相等。

如果文档中也有空行,我喜欢在内容中读取并将其传递给filter以防止空字符串元素

with open(myFile, "r") as f:excludeFileContent = list(filter(None, f.read().splitlines()))

最简单的方法是通过一些额外的好处来做到这一点:

lines = list(open('filename'))

lines = tuple(open('filename'))

lines = set(open('filename'))

set的情况下,我们必须记住,我们没有保留行顺序并删除重复的行。

下面我从@李奇添加了一个重要的补充:

由于您没有在文件对象上调用.close,也没有使用with语句,因此在某些python实现中读取后文件可能不会关闭,您的进程将泄漏打开的文件句柄

CPython(大多数人使用的普通Python实现)中,这不是问题,因为文件对象将立即被垃圾收集,这将关闭文件,但通常认为最好的做法是这样做

with open('filename') as f: lines = list(f)

以确保无论您使用什么python实现都关闭文件。

这是我用来简化文件I/O的Python(3)helper图书馆类:

import os
# handle files using a callback method, prevents repetitiondef _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 filedef read(file_path, mode = "r"):return __file_handler(file_path, mode, lambda rf: rf.read())
# get the lines of a filedef 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(默认检查空行)参数是可选的。

您甚至可以删除readwritedelete方法,只留下FileIO.lines,甚至将其变成一个名为read_lines的单独方法。