【问题标题】:Reading from text file into python list从文本文件读入python列表
【发布时间】:2012-06-22 02:13:32
【问题描述】:

对 python 非常陌生,无法理解为什么这不起作用。我在文本文件中逐行存储了一个网址列表。我想将前 10 个存储在一个名为 bing 的数组/列表中,接下来的 10 个存储在一个名为 yahoo 的列表中,最后 10 个存储在一个名为 dadgo 的列表中。我正在使用readlines 函数将文件中的数据读取到每个数组中。问题是没有任何东西被写入列表。计数按应有的方式递增。此外,如果我完全删除循环并将整个文本文件读入一个列表,它就可以完美地工作。这使我相信循环导致了问题。我正在使用的代码如下。非常感谢一些反馈。

count=0;

#Open the file
fo=open("results.txt","r")

#read into each array
while(count<30):
    if(count<10):
        bing = fo.readlines()
        count+=1
        print bing
        print count

    elif(count>=10 and count<=19):
        yahoo = fo.readlines()
        count+=1
        print count

    elif(count>=20 and count<=29):
        duckgo = fo.readlines()
        count+=1
        print count

print bing
print yahoo
print duckgo

fo.close

【问题讨论】:

    标签: python arrays list loops file-io


    【解决方案1】:

    您正在使用readlines 来读取文件。 readlines 一次读取所有行,因此第一次通过循环时,您会耗尽整个文件并将结果存储在bing 中。然后,每次通过循环时,您都会用下一个readlines 调用的(空)结果覆盖bingyahooduckgo。所以你的清单最后都是空的。

    有很多方法可以解决这个问题。除其他外,您应该考虑一次读取文件一行,使用readline(没有's')。或者更好的是,您可以逐行遍历文件,只需使用 for 循环:

    for line in fo:
        ...
    

    要保持当前代码的结构,您可以使用enumerate

    for line_number, line in enumerate(fo):
        if condition(line_number):
            ...
    

    但坦率地说,我认为您应该放弃当前的系统。更简单的方法是使用 readlines 而不使用循环,然后对结果列表进行切片!

    lines = fo.readlines()
    bing = lines[0:10]
    yahoo = lines[10:20]
    duckgo = lines[20:30]
    

    还有很多其他方法可以做到这一点,有些可能会更好,但没有一个更简单!

    【讨论】:

    • Python 的简单性总是让我惊叹不已。这正是我一直在寻找的,感谢您提供清晰而翔实的答案
    • 哇,这个答案和我开始写的几乎一字不差。别再读我的心思了,senderle!我想这是因为有一种正确的方法来做到这一点。 :)
    • 这没什么大不了的,但是file 是 Python 2.x 中的关键字,我不喜欢将关键字用作变量名。我也喜欢简洁的名字。所以我通常使用f 而不是file 作为打开文件句柄对象的变量。
    • @steveha,是的,我也使用f——我正在编码意识流风格,忘记编辑我的元句法变量。谢谢!为了保持一致,我会选择fo
    【解决方案2】:

    readlines() 读取文件的所有行。如果你再次调用它,你会得到空列表。因此,当您遍历循环时,您正在用空数据覆盖您的列表。

    【讨论】:

      【解决方案3】:

      您应该使用readline() 而不是readlines()

      readlines() 一次读取整个文件,而readline() 从文件中读取一行。

      【讨论】:

        【解决方案4】:

        我建议你这样重写:

        bing = []
        yahoo = []
        duckgo = []
        with open("results.txt", "r") as f:
            for i, line in enumerate(f):
                if i < 10:
                    bing.append(line)
                elif i < 20:
                    yahoo.append(line)
                elif i < 30:
                    duckgo.append(line)
                else:
                    raise RuntimeError, "too many lines in input file"
        

        注意我们如何使用enumerate() 来获取行数,而不是创建我们自己的count 变量并需要自己增加它。这在 Python 中被认为是很好的风格。

        但我认为解决此问题的最佳方法是像这样使用itertools

        import itertools as it
        with open("results.txt", "r") as f:
            bing = list(it.islice(f, 10))
            yahoo = list(it.islice(f, 10)) 
            duckgo = list(it.islice(f, 10))
            if list(it.islice(f, 1)):
                raise RuntimeError, "too many lines in input file"
        

        itertools.islice()(或it.islice(),因为我做了import itertools as it)将从迭代器中提取指定数量的项目。我们打开的文件句柄对象f 是一个从文件中返回行的迭代器,因此it.islice(f, 10) 从输入文件中准确提取了 10 行。

        因为it.islice() 返回一个迭代器,我们必须将它显式地扩展为list,方法是将其包装在list() 中。

        我认为这是最简单的方法。它完美地表达了我们想要的:对于每一个,我们想要一个包含文件中 10 行的列表。根本不需要留一个计数器,每次拉10条线就行了!

        编辑:检查额外行现在使用it.islice(f, 1),因此它只会拉出一行。甚至多出一行就足以知道有超过 30 行预期的行,这样如果有人不小心在一个非常大的文件上运行此代码,它就不会尝试将整个文件吞入内存。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-12-18
          • 2018-05-07
          • 1970-01-01
          • 2015-12-13
          • 1970-01-01
          相关资源
          最近更新 更多