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

How to read a file line-by-line into a list?

提问人:Julie Raswick 提问时间:7/19/2010 最后编辑:martineauJulie Raswick 更新时间:3/28/2023 访问量:4832936

问:

这个问题的答案是社区的努力。编辑现有答案以改进此帖子。它目前不接受新的答案或交互。

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

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

python 字符串 文件 readlines

评论


答:

318赞 Noctis Skytower 7/19/2010 #1

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

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

open返回一个可以迭代的文件。当您循环访问一个文件时,您将从该文件中获取行。 可以获取一个迭代器,并从您提供的迭代器中为您实例化元组实例。 是从文件的行创建的元组。tuplelines

评论

43赞 Noctis Skytower 12/11/2014
@MarshallFarrier 请改为尝试。lines = open(filename).read().split('\n')
26赞 Vanuan 1/3/2015
它会关闭文件吗?
9赞 Noctis Skytower 1/3/2015
@Vanuan 由于运行该行后没有对文件的剩余引用,因此析构函数自动关闭该文件。
39赞 jaynp 5/13/2015
@NoctisSkytower我发现更干净一些,我相信它也能更好地处理 DOS 行结尾。lines = open(filename).read().splitlines()
10赞 Noctis Skytower 1/5/2016
@mklement0 假设一个文件有 1000 行,a 比 .结果来自 。创建 a 所需的时间比创建 (标准差为 0.16%)多 4.17%。结果来自跑步 30 次。当对可变性的需求未知时,我的解决方案更倾向于空间而不是速度。listtuplefrom sys import getsizeof as g; i = [None] * 1000; round((g(list(i)) / g(tuple(i)) - 1) * 100, 2)tuplelistfrom timeit import timeit as t; round((t('tuple(i)', 'i = [None] * 1000') / t('list(i)', 'i = [None] * 1000') - 1) * 100, 2)
712赞 robert 7/19/2010 #2

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

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

评论

45赞 JohannesB 9/19/2018
我更喜欢这个答案,因为它不需要将整个文件加载到内存中(在这种情况下,它仍然会附加到内存中,但可能还有其他情况)。当然,对于大文件,这种方法可能会缓解问题。array
4赞 Elias Strehle 10/4/2018
追加到数组的速度很慢。我想不出这是最佳解决方案的用例。
14赞 AMC 1/10/2020
注意:此解决方案不会剥离换行符。
12赞 andrebrait 5/5/2020
此解决方案确实将整个文件加载到内存中。我不知道为什么人们认为它没有。
3赞 João Monteiro 6/11/2020
@andrebrait 它通过选择将整个文件加载到 lines[] 中,但只能逐行加载。
1210赞 Felix Kling 7/19/2010 #3

请参阅输入和输出

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

或者去掉换行符:

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

评论

104赞 Mark 8/28/2015
更好的是,使用 ,它确实删除了换行符f.read().splitlines()
4赞 Brad Hein 3/4/2016
最好一次读取一行文件,而不是一次将整个文件全部读取到内存中。这样做不能很好地扩展大型输入文件。请看下面罗伯特的回答。
2赞 Ramisa Anjum Aditi 5/11/2018
lines = [x.rstrip('\n') for x in open('data\hsf.txt','r')]如果我这样写,阅读后如何关闭文件?
3赞 Russia Must Remove Putin 5/17/2018
是的,就其他人在这里提出的观点而言,虽然在没有上下文管理器(或其他一些有保证的关闭方式)的情况下使用它不是“最佳实践”,但这并不是真正的情况之一 - 当对象不再引用它时,它将被垃圾回收并关闭文件,这应该在错误与否时立即发生, 当列表推导完成处理时。open
3赞 Mark Amery 9/2/2019
@AaronHall“当对象不再引用它时,它将被垃圾回收并关闭文件”——CPython 是这样,但 PyPy 不是这样。并非所有 Python 实现在不再引用对象时都会立即销毁对象。因此,即使在这种情况下,使用 with 的最佳实践也是相关的。withopen
2924赞 SilentGhost 7/19/2010 #4

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

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 及更高版本中,您可以对 walrus 运算符使用 while 循环,如下所示:

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

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

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

评论

19赞 Tirtha R 3/3/2018
我使用此处提到的过程检查了答案中给出的不同方式的内存配置文件。当从文件中读取并处理每一行时,内存使用率要好得多,正如@DevShark所建议的那样。如果内存是一个约束或文件很大,则将所有行保留在集合对象中不是一个好主意。两种方法的执行时间相似。
2赞 Timo 2/25/2021
我认为这已被弃用。readlines()
3赞 wjandrea 1/25/2022
@Timo 事实并非如此。请参阅文档:io。IOBase.readlines() 中。你认为这是为什么?
6赞 PlasmaHH 5/4/2022
我认为海象版本会停在空行上
2赞 ShadowRanger 10/26/2022
@AlexisWilke:请参阅“:=”语法和赋值表达式:是什么以及为什么?
28赞 Lee 6/18/2013 #5

另一个选项是 numpy.genfromtxt,例如:

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

这将创建一个 NumPy 数组,其中包含与文件中的行数一样多的行数。data

25赞 oliland 11/22/2013 #6

如果要从命令行或 stdin 读取文件,还可以使用该模块:fileinput

# reader.py
import 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

29赞 moldovean 1/12/2014 #7
f = open("your_file.txt",'r')
out = f.readlines() # will append in the list out

现在 variable out 是你想要的列表(数组)。您可以执行以下操作:

for line in out:
    print (line)

艺术

for line in f:
    print (line)

你会得到相同的结果。

234赞 Eneko Alonso 3/2/2014 #8

如果您想要包含:\n

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

如果您不想包括:\n

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

评论

0赞 huang 7/11/2021
太好了,它在每行之间包含空字符串。'1\n2\n3\n' => [ '1', '', '2', '', '3', '' ]
1赞 wjandrea 1/25/2022
@Joke 你一定做错了什么(没有冒犯)。使用 ,返回 。也许您的输入实际上包含空行?s = '1\n2\n3\n's.splitlines()['1', '2', '3']s = '1\n\n2\n\n3\n\n'
30赞 user1833244 5/27/2014 #9

这是对文件使用列表推导式的另一种选择;

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

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

评论

11赞 mklement0 5/23/2015
rstrip()可能会剥离所有尾随空格,而不仅仅是 ;用。\n.rstrip('\n')
2赞 Mark Amery 12/29/2019
这也不能保证文件在所有 Python 实现中读取后都会关闭(尽管在主要的 Python 实现 CPython 中,它会关闭)。
1赞 AMC 1/10/2020
这应该是更有效的方式,因为大部分工作都是在 Python 解释器中完成的。那是什么意思?
0赞 ShadowRanger 10/26/2022
@AMC:使用的措辞是错误的,但是通过listcomp构建相同的代码允许使用一些特殊用途的字节码,这些字节码的运行效率高于手动循环重复调用循环外创建的一些字节码。它仍然在字节码解释器循环中完成大部分工作,只是速度更快一些。要将每个项目的工作完全推送到 CPython 引用解释器上的 C 层,您可以这样做,这将使字节码解释器完全脱离循环。list.append(line.rstrip())listwith open('file.txt') as f: lines = list(map(str.rstrip, f))
45赞 Johnny 12/21/2014 #10

将文件的行读取到列表中的干净和 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 列表,因为它们是可迭代的、高效的和灵活的。在您的例子中,预期的目标是将文本文件的每一行都放入一个单独的元素中。为此,我们将使用 splitlines() 方法,如下所示:

# 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 prea
     frumoas\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ã.
20赞 Jean-Francois T. 2/6/2015 #11

最简单的方法

一个简单的方法是:

  1. 以字符串形式读取整个文件
  2. 逐行拆分字符串

在一行中,这将给出:

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

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

有 2 种更简单的方法:

  1. 使用文件作为迭代器
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')]
  1. 如果您使用的是 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()]

评论

1赞 Mark Amery 12/29/2019
这是一种糟糕的方法。首先,通话在任何方面都不比打电话“简单”。另一方面,它的内存效率低下;您不必要地在内存中同时存储两个版本的文件内容(由 返回的单个字符串和 返回的字符串列表)。.read().splitlines().readlines().read()splitlines()
0赞 Jean-Francois T. 12/31/2019
@MarkAmery 真的。感谢您强调这一点。我已经更新了我的答案。
245赞 Pedro Lobito 4/20/2015 #12

根据 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 mode
lines = f.read().splitlines() # List with stripped line-breaks
f.close() # Close file

评论

1赞 oneturkmen 6/3/2021
第一个示例中的注释行应改为:# my_list = [x.rstrip() for x in f] # remove line breaks# my_list = [x.rstrip() for x in my_list] # remove line breaks
2赞 mightyandweakcoder 9/9/2021
@oneturkmen不,他是对的。他正在循环播放文件中的行。如果该行位于“with”子句之后,您将是正确的
2赞 asampat3090 7/21/2015 #13

您还可以在 NumPy 中使用 loadtxt 命令。这检查的条件比 genfromtxt 少,因此速度可能更快。

import numpy
data = numpy.loadtxt(filename, delimiter="\n")
171赞 DevShark 2/25/2016 #14

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

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

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

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 次即可浏览文件。这通常是泛型解析器的工作方式。

评论

6赞 Ephexx 5/18/2016
这正是我所需要的 - 感谢您解释缺点。作为 Python 的初学者,理解为什么解决方案是解决方案真是太棒了。干杯!
5赞 DevShark 12/13/2016
再想一想,科里。你真的希望你的电脑读取每一行,而不对这些行做任何事情吗?当然,您可以意识到您总是需要以一种或另一种方式处理它们。
6赞 DevShark 12/14/2016
你总是需要对线条做点什么。它可以像打印线条或计数一样简单。让进程读取内存中的行,但不对它执行任何操作是没有价值的。
3赞 DevShark 6/24/2017
你总是需要对他们做点什么。我认为您想表达的观点是,您可能希望一次将一个函数应用于所有这些函数,而不是一个一个地应用。有时确实如此。但从内存的角度来看,这样做的效率非常低,如果文件占用空间大于 Ram,则会阻止您读取文件。这就是为什么通常通用解析器以我描述的方式运行的原因。
2赞 DevShark 9/14/2017
@PierreOcinom这是正确的。鉴于文件是以只读模式打开的,则无法使用上述代码修改原始文件。要打开文件进行读取和写入,请使用open('file_path', 'r+')
5赞 Zero 3/30/2016 #15

使用这个:

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

data是 DataFrame 类型,并使用值获取 ndarray。您还可以使用 获取列表。array.tolist()

评论

0赞 AMC 1/10/2020
pandas.read_csv()用于读取CSV数据,这里怎么合适?
15赞 Abdullah Bilal 9/9/2016 #16

只需使用 splitlines() 函数。下面是一个示例。

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

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

评论

0赞 Mark Amery 12/29/2019
与使用 相比,内存效率低下。这会将文件内容的两个副本同时放入内存中(一个是单个大字符串,一个是行列表)。.readlines()
1赞 physicalattraction 9/4/2020
但是它更容易阅读,与易于阅读代码相比,内存并不总是一个问题。data.read().splitlines()
11赞 pambda 3/11/2017 #17

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

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

评论

0赞 Newskooler 4/6/2017
process(line) 是做什么的?我收到一个错误,说没有定义这样的变量。我想有些东西需要导入,我尝试导入多处理。过程,但我想不是这样。你能详细说明一下吗?谢谢
1赞 Khanal 4/26/2017
process(line)是处理数据时需要实现的函数。例如,如果使用 ,它将打印lines_buffer中的每一行,而不是该行。print(line)
0赞 David Dehghan 6/30/2018
f.readlines(buffersize) 返回一个不可变的缓冲区。如果你想直接读入你的缓冲区,你需要使用 readinto() 函数。我会快得多。
105赞 PythonProgrammi 4/26/2017 #18

具有文本文件内容:

line 1
line 2
line 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']

评论

1赞 Mausy5043 6/3/2018
是必需的吗?encoding="utf-8"
1赞 Eric O. Lebigot 10/23/2018
read().splitlines()由 Python 提供:它很简单(可能更快,因为它浪费更少)。readlines()
3赞 craq 6/4/2020
@EricOLebigot从所示示例来看,它看起来和不产生相同的输出。你确定它们是等价的吗?read().splitlines()readlines()
2赞 PythonProgrammi 6/4/2020
如果仅使用readlines,则需要使用strip方法删除文本中的\n,因此我使用列表推导式更改了最后一个示例,以在两种情况下具有相同的输出。因此,如果您使用 read().readlines(),您将拥有一个带有行且没有换行符的“干净”项,否则,您必须执行上面代码中看到的操作。
1赞 Eric O. Lebigot 6/5/2020
事实上。请注意,在上面的代码中,删除了一行周围的所有应变或空格。此外,在列表理解中做是没有意义的:简单地迭代文件会更好,因为它不会通过创建行的中间列表来浪费时间和内存。strip()rstrip("\n")readlines()
0赞 jasonleonhard 8/30/2017 #19

命令行版本

#!/bin/python3
import os
import sys
abspath = 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

评论

1赞 mah 3/19/2021
你到底为什么要要求文本文件位于你的 python 脚本所在的同一目录中?相反,无论指定了相对路径还是绝对路径,它都会起作用,并且它不会关心您的脚本位于何处。open(sys.argv[1])
27赞 Martin Thoma 1/17/2018 #20

使用 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()lines

常见文件结尾

.txt

更高级的文件写入/读取

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

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

另请参阅:数据序列化格式的比较

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

47赞 MSeifert 1/17/2018 #21

若要将文件读入列表,需要执行以下三项操作:

  • 打开文件
  • 读取文件
  • 将内容存储为列表

幸运的是,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

第二个参数是 ,默认情况下,它表示“只读”。这正是您所需要的。moder

但是,如果您确实想要创建文件和/或写入文件,则需要在此处使用不同的参数。如果您想要概述,有一个很好的答案

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

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

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

open(filename, 'rb')

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


现在我已经演示了如何创建文件,让我们谈谈您总是需要再次使用它的事实。否则,它将保留文件的打开文件句柄,直到进程退出(或 Python 对文件句柄进行垃圾处理)。openclose

虽然您可以使用:

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

当 和 之间的东西引发异常时,将无法关闭文件。您可以通过使用 和 来避免这种情况:openclosetryfinally

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

但是,Python 提供了具有更漂亮语法的上下文管理器(但它几乎与上述语法相同):opentryfinally

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

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

读取文件

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

该函数返回一个文件对象,它支持 Python 迭代协议。每次迭代都会给你一行:open

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

这将打印文件的每一行。但请注意,每行末尾都会包含一个换行符(你可能想检查你的 Python 是否支持通用换行符 - 否则你也可能在 Windows 或 Mac 上作为换行符)。如果您不想这样做,可以简单地删除最后一个字符(或Windows上的最后两个字符):\n\r\n\r

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())

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

将内容存储为列表

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

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

如果你想去掉尾随的换行符,你可以改用列表推导式:

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

或者更简单:默认情况下,对象的 .readlines() 方法返回以下行:filelist

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

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

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

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()

评论

1赞 AMC 1/10/2020
最后一种方法是在 Python 中打开文件的推荐方法!那么,为什么它是最后的呢?绝大多数人不会在继续之前看一眼答案的前几行吗?
0赞 MSeifert 1/10/2020
@AMC 当我写答案时,我没有花太多心思。你认为我应该把它放在答案的顶部吗?
0赞 AMC 1/10/2020
这可能是最好的,是的。我也刚刚注意到你提到了 Python 2,所以也可以更新。
0赞 MSeifert 1/10/2020
啊,这个问题最初被标记为 python-2.x。更普遍地更新它可能很有意义。我会看看下次我是否来那个。感谢您的建议。非常感谢!
2赞 Daniel 3/29/2018 #22

我喜欢使用以下内容。立即阅读这些行。

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

或者使用列表推导式:

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

评论

3赞 Eric O. Lebigot 10/23/2018
不需要 ,这甚至会导致记忆损失。您可以简单地删除它,因为遍历(文本)文件会依次给出每一行。readlines()
3赞 Aran-Fey 10/30/2018
应使用语句打开(并隐式关闭)文件。with
53赞 LangeHaare 5/1/2018 #23

在 Python 3.4 中引入的 pathlib 提供了一种非常方便的方法,用于从文件中读取文本,如下所示:

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

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

pathlib里面有很多方便的便利。read_text简洁明了,您不必担心打开和关闭文件。如果您只需要一次性读取文件,那么这是一个不错的选择。

4赞 Russia Must Remove Putin 5/17/2018 #24

大纲和摘要

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

  • list(fileinput.input(filename))
  • 使用 , 调用with path.open() as ff.readlines()
  • list(f)
  • path.read_text().splitlines()
  • path.read_text().splitlines(keepends=True)
  • 一次遍历一行或每一行fileinput.inputflist.append
  • 传递给绑定方法flist.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

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

在 Python 中,如何逐行将文件读入列表?

啊,但出于某种原因,您希望它出现在列表中?如果可能的话,我会避免这种情况。但如果你坚持......只需将结果传递给:fileinput.input(filename)list

list(fileinput.input(filename))

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

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

filename = 'filename'

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

或者使用模块中的新 Path 对象(我已经非常喜欢它,并且将从这里开始使用):pathlib

from pathlib import Path

path = Path(filename)

with path.open() as f:
    f.readlines()

list还将使用文件迭代器并返回一个列表 - 这也是一种非常直接的方法:

with path.open() as f:
    list(f)

如果您不介意在拆分之前将整个文本作为单个字符串读入内存,则可以将其作为带有对象和字符串方法的单行代码来执行。默认情况下,删除换行符:Pathsplitlines()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.inputwith path.open() as f

3赞 Siddharth Satpathy 12/19/2018 #25

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

在下面提到的两个示例中,所需的列表由 给出。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. 在第二种方法中,可以使用 Python 标准库中的 csv.reader 模块

import csv
fpath = '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

评论

1赞 Charlie Harding 1/2/2019
第二种方法的优点是什么?为什么要调用一个额外的库,它添加了边缘情况(分隔符和引号)?
1赞 AMC 1/10/2020
论据是什么?delimiter=' '
5赞 jeanggi90 1/17/2019 #26

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

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

评论

2赞 AMC 1/10/2020
这是不谚蛇的,要小心。
0赞 ShadowRanger 10/26/2022
使用 保存一些大型中间临时 ,或者,要保留非换行符尾随空格(用作映射器函数会去除任何和所有类型的尾随空格),请添加 import () 并执行 .excludeFileContent = list(filter(None, map(str.rstrip, f)))str.rstripfrom operator import methodcallerexcludeFileContent = list(filter(None, map(methodcaller('rstrip', '\n'), f)))
7赞 simhumileco 3/14/2019 #27

最简单的方法,以及一些额外的好处是:

lines = list(open('filename'))

lines = tuple(open('filename'))

lines = set(open('filename'))

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

下面我添加了@MarkAmery的重要补充:

由于您既不调用文件对象也不使用语句,因此在某些 Python 实现中,文件在读取后可能不会关闭,并且您的进程将泄漏打开的文件句柄.closewith

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

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

以确保无论您使用哪种 Python 实现,文件都会关闭。

评论

3赞 Mark Amery 12/29/2019
由于您既不调用文件对象也不使用语句,因此在某些 Python 实现中,文件在读取后可能不会关闭,并且您的进程将泄漏打开的文件句柄。在 CPython(大多数人使用的普通 Python 实现)中,这不是问题,因为文件对象会立即被垃圾回收,这将关闭文件,但通常认为最佳实践是确保文件被关闭,无论您使用什么 Python 实现。.closewithwith open('filename') as f: lines = list(f)
0赞 simhumileco 12/30/2019
感谢您@MarkAmery的精彩评论!我真的很感激。
1赞 AMC 1/10/2020
@simhumileco 为什么最佳(正确)解决方案会持续下去?
0赞 simhumileco 1/10/2020
@AMC因为首先,我想展示最简单的方法和推理的一致性。
0赞 simhumileco 1/10/2020
此外,我希望我的回答简短易读。
1赞 Malekai 4/20/2019 #28

下面是一个 Python(3) 辅助类,我用它来简化文件 I/O:

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

您甚至可以删除 和 方法,只保留 ,甚至将其转换为一个名为 的单独方法。readwritedeleteFileIO.linesread_lines

评论

1赞 Mark Amery 12/29/2019
真的比证明这个帮手的存在要简单吗?每次调用可以节省 17 个字符。(大多数时候,出于性能和内存原因,您需要直接遍历文件对象,而不是将其行读入列表,因此您甚至不想经常使用它!我经常喜欢创建一些实用函数,但在我看来,它只是不必要地创造了一种新的方法来编写一些已经很短很简单的东西。lines = FileIO.lines(path)with open(path) as f: lines = f.readlines()
1赞 AMC 1/10/2020
除了@MarkAmery所说的之外,为什么要为此使用类呢?