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


2027

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

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

Answers:


2174
with open(filename) as f:
    content = f.readlines()
# you may also want to remove whitespace characters like `\n` at the end of each line
content = [x.strip() for x in content] 

206
不要file.readlines()for-loop中使用文件对象本身就足够了:lines = [line.rstrip('\n') for line in file]
jfs 2015年

88
在使用大数据的情况下,使用readlines()效率不是很高,因为它可能导致MemoryError。在这种情况下,最好使用for line in f:每个line变量并对其进行操作来遍历文件。
DarkCygnus

7
我使用此处提到的过程检查了答案中给出的不同方式的内存配置文件。从文件中读取并处理每一行时,内存使用情况要好得多,这是@DevShark 在此处建议的。如果内存是一个约束或文件很大,则将所有行都保存在集合对象中并不是一个好主意。两种方法的执行时间相似。
Tirtha R

6
另外,.rstrip()如果要从行尾去除空白,则工作速度会稍快一些。
Gringo Suave

1002

请参阅输入和输出

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

或通过删除换行符:

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

12
更好,请使用f.read().splitlines(),它确实会删除换行符
标记

是第二版,for line in open(filename)安全吗?也就是说,文件会自动关闭吗?
becko '16

2
最好一次只读取一行文件,而不是一次将整个文件都读取到内存中。这样做对于大型输入文件而言无法很好地扩展。请参阅以下罗伯特的答案。
布莱德·海因

1
lines = [x.rstrip('\n') for x in open('data\hsf.txt','r')]如果以这种方式编写,读取后如何关闭文件?
Ramisa Anjum Aditi

2
是的,至于其他人在这里提出的观点是,open没有上下文管理器(或其他保证关闭它的方法)不是“最佳实践” ,但这实际上不是这些情况之一-当对象没有更多引用时它将被垃圾收集并关闭文件,当完成列表理解处理后,无论是否发生错误,都应立即发生。
亚伦·霍尔

578

这比必要的要明确,但是可以满足您的要求。

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

18
我更喜欢这个答案,因为它不需要将整个文件加载到内存中(在这种情况下,array虽然它仍附加在文件中,但是可能还有其他情况)。当然,对于大文件,此方法可以缓解问题。
JohannesB

1
追加到数组很慢。我无法想到这是最佳解决方案的用例。
Elias Strehle,

@haccks会更好,因为它不会将整个文件加载到内存中还是还有更多?
OrigamiEye '18

4
注意:此解决方案不会删除换行符。
AMC

1
此解决方案确实将整个文件加载到内存中。我不知道为什么人们会这样认为。
andrebrait

274

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

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

open返回可以迭代的文件。遍历文件时,您将从该文件中获取行。tuple可以使用一个迭代器,并从赋予它的迭代器中实例化一个元组实例。lines是从文件行创建的元组。


30
@MarshallFarrier试试看lines = open(filename).read().split('\n')
Noctis Skytower 2014年

16
它会关闭文件吗?
Vanuan 2015年

5
@Vanuan由于在运行该行之后没有剩余的文件引用,因此析构函数自动关闭文件。
Noctis Skytower

30
@NoctisSkytower我发现lines = open(filename).read().splitlines()它更干净一些,并且我相信它还能更好地处理DOS行尾。
杰恩普

8
@ mklement0假设文件包含1000行,则a list比a占用约13.22%的空间tuple。结果来自from sys import getsizeof as g; i = [None] * 1000; round((g(list(i)) / g(tuple(i)) - 1) * 100, 2)。创建a tuple所需的时间比创建a list(标准偏差为0.16%)的时间长约4.17%。结果来自运行from timeit import timeit as t; round((t('tuple(i)', 'i = [None] * 1000') / t('list(i)', 'i = [None] * 1000') - 1) * 100, 2)30次。当对可变性的需求未知时,我的解决方案倾向于空间而不是速度。
Noctis Skytower


168

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

with open('file.txt') as f:
    my_list = list(f)

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

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().split("\n") # Create a list containing all lines
f.close() # Close file

149

如建议的那样,您可以简单地执行以下操作:

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该类的实现留给您练习)。

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


5
这正是我所需要的-感谢您解释缺点。作为Python的初学者,了解为什么解决方案就是解决方案真是太棒了。干杯!
Ephexx '16

5
多想科里。您是否真的想让计算机读取每一行,而不用对这些行做任何事情?当然,您可以意识到您始终需要以一种或另一种方式处理它们。
DevShark

5
您总是需要做一些事情。可以简单地打印行或对行进行计数。让您的进程读取内存中的行没有任何价值,但不对其执行任何操作。
DevShark

2
您总是需要对他们做一些事情。我认为您要提出的观点是,您可能希望一次将功能应用于所有这些功能,而不是一个接一个地应用。有时候确实是这样。但是从内存的角度来看这样做是非常低效的,并且如果占用空间大于Ram,则会阻止您读取文件。这就是为什么通用解析器通常按照我所描述的方式运行的原因。
DevShark

2
@PierreOcinom是正确的。鉴于该文件是以只读模式打开的,因此您无法使用上述代码修改原始文件。要打开文件进行读写,请使用open('file_path', 'r+')
DevShark

62

数据入列表

假设我们有一个文本文件,其数据如下行所示,

文字档内容:

line 1
line 2
line 3
  • 在同一目录中打开cmd(右键单击鼠标,然后选择cmd或PowerShell)
  • 运行python并在解释器中编写:

Python脚本:

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

使用追加:

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']

要么:

>>> y = [x.rstrip() for x in open("my_file.txt")]
>>> y
['line 1','line 2','line 3']


with open('testodiprova.txt', 'r', encoding='utf-8') as file:
    file = file.read().splitlines()
  print(file)

with open('testodiprova.txt', 'r', encoding='utf-8') as file:
  file = file.readlines()
  print(file)

encoding="utf-8"必需的吗?
Mausy5043

@ Mausy5043不,但是当您阅读文本文件时,您可能会有一些奇怪的字符(尤其是意大利语)
Giovanni G. PY18年

1
read().splitlines()是由Python提供给您的:它很简单readlines()(可能会更快,因为它浪费更少)。
Eric O Lebigot

43

要将文件读入列表,您需要做三件事:

  • 开启档案
  • 读取文件
  • 将内容存储为列表

幸运的是,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'(二进制模式)将被忽略。


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

虽然您可以使用:

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

当两者之间存在openclose引发异常时,将无法关闭文件。您可以使用try和来避免这种情况finally

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

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

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

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

读取文件

好的,您已经打开了文件,现在如何读取?

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

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

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

将内容存储为列表

现在您知道了如何打开文件并阅读它,是时候将内容存储在列表中了。最简单的选择是使用以下list功能:

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

如果要删除尾随的换行符,可以使用列表理解:

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

或更简单:默认情况下.readlines()file对象的方法返回list以下行中的a:

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

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

还有一个额外的选项来获得所需的输出,但是它是“次优的”:read将整个文件放在字符串中,然后在换行符上分割:

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()但是如果您要在将行存储到列表中之前对其进行处理,我建议您使用简单的列表理解。

最后一种方法是建议使用Python打开文件的方法!那为什么最后呢?绝大多数人会在继续之前只是看一眼答案的前几行吗?
AMC

@AMC在编写答案时,我并没有考虑太多。您认为我应该把它放在答案的顶部吗?
MSeifert

可能是最好的,是的。我还注意到您提到了Python 2,因此也可以进行更新。
AMC

嗯,这个问题最初被标记为python-2.x。更一般地更新它可能很有意义。我下次再来看。感谢您的建议。非常感激!
MSeifert

42

将文件中的行读入列表的简洁Python方式


首先,最重要的是,您应该专注于以高效且Python方式打开文件并读取其内容。这是我个人不喜欢的方式的一个示例:

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ã.

30

在Python 3.4中引入,它pathlib具有从文件中读取文本的非常方便的方法,如下所示:

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

(该splitlines调用使它从包含文件全部内容的字符串变成文件中的行列表)。

pathlib有很多方便的地方。read_text简洁明了,您不必担心打开和关闭文件的麻烦。如果您需要一次性处理所有文件,那么这是一个不错的选择。


29

通过对文件使用列表推导,这是另一个选择。

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

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


10
rstrip()可能会剥离所有尾随的空格,而不仅是\n; 使用.rstrip('\n')
mklement0

这也不能保证在所有Python实现中都将关闭文件(尽管在CPython中,它是主要的Python实现)。
Mark Amery

1
这应该是一种更有效的方法,因为大部分工作都在Python解释器中完成。这意味着什么?
AMC

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

您将获得相同的结果。


27

使用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中的配置文件》


26

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

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

这将使dataNumPy数组具有与文件中一样多的行。


25

如果您想从命令行或标准输入中读取文件,也可以使用以下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


20

最简单的方法

一种简单的方法是:

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

这是一个不好的方法。一方面,调用.read().splitlines()并不比仅调用“简单” .readlines()。另外,它的内存效率低下;您无需一次将两个版本的文件内容(由返回的单个字符串.read()和由返回的字符串列表splitlines())存储在内存中。
Mark Amery

@MarkAmery是的。感谢您强调这一点。我已经更新了答案。
Jean-Francois T.

14

只需使用splitlines()函数。这是一个例子。

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

在输出中,您将具有行列表。


与使用相比,内存效率低下.readlines()。这会将文件内容的两个副本一次放入内存中(一个作为单个大字符串,一个作为行列表)。
Mark Amery

11

如果您想要面对一个非常大的文件,并且想要更快读取(假设您正在参加Topcoder / Hackerrank编码竞赛),则可以一次将相当大的几行读取到内存缓冲区中,而不是一次只是在文件级别逐行迭代。

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)

流程(生产线)做什么?我收到一个错误,没有定义这样的变量。我猜有些东西需要导入,我尝试导入multiprocessing.Process,但这不是我想的。您能详细说明一下吗?谢谢
Newskooler

1
process(line)是处理数据需要实现的功能。例如,如果使用而不是该行,print(line)它将从lines_buffer打印每一行。
哈纳尔

f.readlines(buffersize)返回一个不可变的缓冲区。如果您想直接读入缓冲区,则需要使用readinto()函数。我会更快。
David Dehghan

7

实现此目标的最简单方法是:

lines = list(open('filename'))

要么

lines = tuple(open('filename'))

要么

lines = set(open('filename'))

在使用的情况下set,必须记住,我们没有保留行顺序并摆脱了重复的行。

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

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

CPython(大多数人使用的普通Python实现)中,这不是问题,因为文件对象将立即被垃圾收集并关闭文件,但是,尽管如此,它仍被认为是最佳实践,例如

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

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


1
由于您既不调用.close文件对象也不使用with语句,因此在某些Python实现中,文件在读取后可能不会关闭,并且您的进程将泄漏打开的文件句柄。在CPython(大多数人使用的普通Python实现)中,这不是问题,因为文件对象将立即被垃圾回收,这将关闭文件,但是,尽管如此,做为with open('filename') as f: lines = list(f)确保以下内容的方法仍被认为是最佳做法:无论您使用哪种Python实现,文件都会关闭。
Mark Amery

谢谢您对@MarkAmery的好评!我真的很感激。
simhumileco

1
@simhumileco为什么最后有最好的(正确)解决方案?
AMC

@AMC,因为首先,我想展示最简单的方法并保持推理的一致性。
simhumileco

另外,我希望我的回答简短易读。
simhumileco

4

用这个:

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

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


pandas.read_csv()用于读取CSV数据,在这里合适吗?
AMC

4

概述和总结

使用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.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在两者之上都是返回懒惰迭代器。您只能使用一次迭代器,因此在提供功能代码的同时避免了冗长性,我将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()

或使用新的Path对象 pathlib模块中(我已经很喜欢它,并将在此处使用):

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(fileinput.input(filename))

结论

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

也就是说,首选fileinput.inputwith path.open() as f


4

如果文档中也有空行,我希望阅读内容并将其传递filter以防止空字符串元素

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

1
这是不可思议的,要小心。
AMC

3

您也可以在NumPy中使用loadtxt命令。与genfromtxt相比,此方法检查的条件较少,因此可能更快。

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

2

我喜欢使用以下内容。立即阅读线路。

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

或使用列表理解:

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

2
不需要readlines(),甚至会导致内存损失。您可以简单地将其删除,因为遍历(文本)文件会依次显示每一行。
Eric O Lebigot

2
您应该使用一条with语句打开(并隐式关闭)文件。
阿兰·菲

2

我会尝试以下提到的方法之一。我使用的示例文件的名称为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.>第二种方法中,可以使用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
第二种方法的优势是什么?为什么要调用一个额外的库,该库增加了某些情况(定界符和引号)?
查理·哈丁

什么是delimiter=' '对的说法?
AMC

2

这是我用来简化文件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(默认情况下检查空行)参数是可选的。

你甚至可以删除readwrite以及delete方法和刚离开FileIO.lines,甚至把它变成所谓的一个单独的方法read_lines


lines = FileIO.lines(path)真的够简单得多with open(path) as f: lines = f.readlines()证明这个辅助的存在?您每次通话可节省17个字符。(而且在大多数情况下,出于性能和内存方面的原因,您将希望直接循环遍历文件对象,而不是始终将其行读入列表,因此您甚至不想经常使用它!)经常喜欢创建一些小的实用函数,但是我觉得这就像不必要地创建一种新的方法,用标准库为我们编写已经很简单的东西。
Mark Amery

除了@MarkAmery所说的以外,为什么还要为此使用类?
AMC

1

命令行版本

#!/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
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.