关于python:仅读取特定行

Reading specific lines only

我使用for循环来读取文件,但我只想读取特定的行,比如第26行和第30行。是否有任何内置功能来实现这一点?

谢谢


如果要读取的文件很大,并且您不想同时读取内存中的整个文件:

1
2
3
4
5
6
7
8
9
fp = open("file")
for i, line in enumerate(fp):
    if i == 25:
        # 26th line
    elif i == 29:
        # 30th line
    elif i > 29:
        break
fp.close()

注意,i == n-1用于n第一线。

在python 2.6或更高版本中:

1
2
3
4
5
6
7
8
with open("file") as fp:
    for i, line in enumerate(fp):
        if i == 25:
            # 26th line
        elif i == 29:
            # 30th line
        elif i > 29:
            break


快速回答:

1
2
3
4
f=open('filename')
lines=f.readlines()
print lines[25]
print lines[29]

或:

1
2
3
4
5
6
7
lines=[25, 29]
i=0
f=open('filename')
for line in f:
    if i in lines:
        print i
    i+=1

对于提取多行有一个更优雅的解决方案:linecache(由"python:How to jump to a specific line in a great text file?"提供)。上一个stackoverflow.com问题)。

引用上面链接的python文档:

1
2
3
4
>>> import linecache
>>> linecache.getline('/etc/passwd', 4)
'sys:x:3:3:sys:/dev:/bin/sh
'

4改成你想要的行号,你就接通了。请注意,4将带第五行,因为计数以零为基础。

如果文件可能非常大,并且在读取内存时会导致问题,那么最好接受@alok的建议并使用enumerate()。

总结如下:

  • 使用fileobject.readlines()for line in fileobject作为小文件的快速解决方案。
  • 使用linecache获得更优雅的解决方案,这对于读取多个文件来说速度相当快,可以反复使用。
  • 接受@alok的建议,并使用enumerate()处理可能非常大且无法放入内存的文件。请注意,使用此方法可能会变慢,因为文件是按顺序读取的。


快速而紧凑的方法可以是:

1
2
def picklines(thefile, whatlines):
  return [x for i, x in enumerate(thefile) if i in whatlines]

它接受任何打开的文件,如对象thefile(由调用者决定是从磁盘文件还是通过套接字或其他类似文件流的方式打开)和一组基于零的行索引whatlines,并返回一个列表,内存占用量低,速度合理。如果要返回的行数很大,您可能更喜欢生成器:

1
2
def yieldlines(thefile, whatlines):
  return (x for i, x in enumerate(thefile) if i in whatlines)

这基本上只适用于循环——注意,唯一的区别在于在return语句中使用圆括号而不是方括号,分别进行列表理解和生成器表达式。

还要注意的是,尽管提到了"行"和"文件",这些函数还是非常通用的——它们可以处理任何不可重复的项目,无论是打开的文件还是其他任何文件,根据项目的渐进编号返回项目列表(或生成器)。所以,我建议使用更合适的通用名称;-)。


为了提供另一种解决方案:

1
2
import linecache
linecache.getline('Sample.txt', Number_of_Line)

我希望这是快速和容易的:)


如果你想要第7行

1
line = open("file.txt","r").readlines()[7]


读取文件的速度非常快。读取一个100MB文件需要不到0.1秒的时间(请参阅我的文章用Python读写文件)。因此,您应该完整地阅读它,然后使用单行。

这里大多数的答案都不是错的,而是不好的风格。打开文件应该总是用with完成,因为它可以确保文件再次关闭。

所以你应该这样做:

1
2
3
4
with open("path/to/file.txt") as f:
    lines = f.readlines()
print(lines[26])  # or whatever you want to do with this line
print(lines[30])  # or whatever you want to do with this line

。大文件

如果您碰巧有一个巨大的文件,并且内存消耗是一个问题,那么您可以一行一行地处理它:

1
2
3
with open("path/to/file.txt") as f:
    for i, line in enumerate(f):
        pass  # process line i


为了完整起见,这里还有一个选择。

让我们从python文档的定义开始:

slice An object usually containing a portion of a sequence. A slice is created using the subscript notation, [] with colons between numbers when several are given, such as in variable_name[1:3:5]. The bracket (subscript) notation uses slice objects internally (or in older versions, __getslice__() and __setslice__()).

虽然slice表示法一般不直接适用于迭代器,但是itertools包包含一个替换函数:

1
2
3
4
5
6
7
8
9
10
11
from itertools import islice

# print the 100th line
with open('the_file') as lines:
    for line in islice(lines, 99, 100):
        print line

# print each third line until 100
with open('the_file') as lines:
    for line in islice(lines, 0, 100, 3):
        print line

该函数的另一个优点是,它直到结束时才读取迭代器。所以你可以做更复杂的事情:

1
2
3
4
5
6
7
8
9
10
11
12
with open('the_file') as lines:
    # print the first 100 lines
    for line in islice(lines, 100):
        print line

    # then skip the next 5
    for line in islice(lines, 5):
        pass

    # print the rest
    for line in lines:
        print line

回答最初的问题:

1
2
3
# how to read lines #26 and #30
In [365]: list(islice(xrange(1,100), 25, 30, 4))
Out[365]: [26, 30]


其中一些很可爱,但可以做得更简单:

1
2
3
4
5
6
7
8
start = 0 # some starting index
end = 5000 # some ending index
filename = 'test.txt' # some file we want to use

with open(filename) as fh:
    data = fin.readlines()[start:end]

print(data)

这将使用简单的列表切片,它加载整个文件,但大多数系统将适当地最小化内存使用,它比上面给出的大多数方法都快,并在我的10g+数据文件上工作。祝你好运!


可以执行seek()调用,将读取头定位到文件中的指定字节。除非您确切知道要读取的行之前文件中写入了多少字节(字符),否则这对您没有帮助。也许您的文件是严格格式化的(每行是x字节数?)或者,如果你真的想提高速度,你可以自己计算字符数(记住要包括不可见的字符,如换行符)。

否则,您必须按照这里已经提出的许多解决方案之一,在您想要的行之前阅读每一行。


我更喜欢这种方法,因为它更通用,也就是说,您可以在文件中、在f.readlines()的结果中、在StringIO对象中使用它,无论:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def read_specific_lines(file, lines_to_read):
  """file is any iterable; lines_to_read is an iterable containing int values"""
   lines = set(lines_to_read)
   last = max(lines)
   for n, line in enumerate(file):
      if n + 1 in lines:
          yield line
      if n + 1 > last:
          return

>>> with open(r'c:\temp\words.txt') as f:
        [s for s in read_specific_lines(f, [1, 2, 3, 1000])]
['A
'
, 'a
'
, 'aa
'
, 'accordant
'
]


阿洛克·辛哈尔的回答的一个更好和微小的改变

1
2
3
4
5
6
7
8
9
fp = open("file")
for i, line in enumerate(fp,1):
    if i == 26:
        # 26th line
    elif i == 30:
        # 30th line
    elif i > 30:
        break
fp.close()

这个怎么样:

1
2
3
4
5
>>> with open('a', 'r') as fin: lines = fin.readlines()
>>> for i, line in enumerate(lines):
      if i > 30: break
      if i == 26: dox()
      if i == 30: doy()


如果您不介意导入,那么fileinput将完全满足您的需要(这是您可以读取当前行的行号)。


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def getitems(iterable, items):
  items = list(items) # get a list from any iterable and make our own copy
                      # since we modify it
  if items:
    items.sort()
    for n, v in enumerate(iterable):
      if n == items[0]:
        yield v
        items.pop(0)
        if not items:
          break

print list(getitems(open("/usr/share/dict/words"), [25, 29]))
# ['Abelson
', 'Abernathy
']
# note that index 25 is the 26th item


这是我的2美分,值多少钱;)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def indexLines(filename, lines=[2,4,6,8,10,12,3,5,7,1]):
    fp   = open(filename,"r")
    src  = fp.readlines()
    data = [(index, line) for index, line in enumerate(src) if index in lines]
    fp.close()
    return data


# Usage below
filename ="C:\\Your\\Path\\And\\Filename.txt"
for line in indexLines(filename): # using default list, specify your own list of lines otherwise
    print"Line: %s
Data: %s
"
% (line[0], line[1])


如果您的大文本文件file结构严格(意味着每行的l长度相同),则可以使用n第行。

1
2
3
4
with open(file) as f:
    f.seek(n*l)
    line = f.readline()  # please notice the s at the end!
    last_pos = f.tell()

免责声明:这只适用于相同长度的文件!


打印第3行,

1
2
3
4
5
6
7
8
9
line_number = 3

with open(filename,"r") as file:
current_line = 1
for line in file:
    if current_line == line_number:
        print(file.readline())
        break
    current_line += 1

原作者:弗兰克·霍夫曼


@你可以用枚举

1
2
3
for n,line in enumerate(open("file")):
    if n+1 in [26,30]: # or n in [25,29]
       print line.rstrip()


您可以使用前面提到的语法非常简单地做到这一点,但这是迄今为止最简单的方法:

1
2
3
4
inputFile = open("lineNumbers.txt","r")
lines = inputFile.readlines()
print (lines[0])
print (lines[2])


文件对象有一个.readlines()方法,它将为您提供文件内容的列表,每个列表项一行。之后,您可以使用普通的列表切片技术。

http://docs.python.org/library/stdtypes.html_file.readlines


1
2
3
4
file = '/path/to/file_to_be_read.txt'
with open(file) as f:
    print f.readlines()[26]
    print f.readlines()[30]

使用WITH语句,将打开文件,打印第26行和第30行,然后关闭文件。简单!


很快就到了。

在文本文件中打印某些行。创建"lines2print"列表,然后仅当枚举"在"行2打印列表中时打印。若要清除多余的'',请使用line.strip()或line.strip('')。我只是喜欢"列表理解",并尽可能地使用。我喜欢用"with"方法读取文本文件以防止以任何理由打开文件。

1
2
3
4
lines2print = [26,30] # can be a big list and order doesn't matter.

with open("filepath", 'r') as fp:
    [print(x.strip()) for ei,x in enumerate(fp) if ei in lines2print]

或者如果列表很小,只需将列表作为列表键入理解。

1
2
with open("filepath", 'r') as fp:
    [print(x.strip()) for ei,x in enumerate(fp) if ei in [26,30]]


打印所需行。在所需行的上方/下方打印行。

1
2
3
4
5
6
def dline(file,no,add_sub=0):
    tf=open(file)
    for sno,line in enumerate(tf):
        if sno==no-1+add_sub:
         print(line)
    tf.close()

执行---->d line("d:dummy.txt",6),即dline("文件路径",行号,如果希望搜索行的上行给出1表示下行-1,这是可选的默认值,将取0)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
f = open(filename, 'r')
totalLines = len(f.readlines())
f.close()
f = open(filename, 'r')

lineno = 1
while lineno < totalLines:
    line = f.readline()

    if lineno == 26:
        doLine26Commmand(line)

    elif lineno == 30:
        doLine30Commmand(line)

    lineno += 1
f.close()


我想这行

1
2
3
4
5
6
 open_file1 = open("E:\\test.txt",'r')
 read_it1 = open_file1.read()
 myline1 = []
 for line1 in read_it1.splitlines():
 myline1.append(line1)
 print myline1[0]