簡體   English   中英

在Python中從文件(但不是全部)讀取n行

[英]Reading n lines from file (but not all) in Python

如何在迭代時從文件中讀取n行而不是只讀一行? 我有一個具有良好定義結構的文件,我想做這樣的事情:

for line1, line2, line3 in file:
    do_something(line1)
    do_something_different(line2)
    do_something_else(line3)

但它不起作用:

ValueError:要解壓縮的值太多

現在我這樣做:

for line in file:
    do_someting(line)
    newline = file.readline()
    do_something_else(newline)
    newline = file.readline()
    do_something_different(newline)
... etc.

這很糟糕,因為我正在編寫無休止的' newline = file.readline() ',它們使代碼混亂。 有沒有聰明的方法來做到這一點? (我真的想避免一次讀取整個文件,因為它很大)

基本上,您的file是一個迭代器,它一次產生一行文件。 這會將您的問題轉化為如何從迭代器一次產生多個項目。 這個問題中給出了解決方案。 請注意,函數islice位於itertools模塊中,因此您必須從那里導入它。

如果它是xml為什么不只是使用lxml?

您可以使用這樣的輔助函數:

def readnlines(f, n):
    lines = []
    for x in range(0, n):
        lines.append(f.readline())
    return lines

然后你可以做你想要的事情:

while True:
    line1, line2, line3 = readnlines(file, 3)
    do_stuff(line1)
    do_stuff(line2)
    do_stuff(line3)

話雖這么說,如果你使用的是xml文件,如果使用真正的xml解析器,從長遠來看你可能會更開心......

itertools救援:

import itertools
def grouper(n, iterable, fillvalue=None):
    "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx"
    args = [iter(iterable)] * n
    return itertools.izip_longest(fillvalue=fillvalue, *args)


fobj= open(yourfile, "r")
for line1, line2, line3 in grouper(3, fobj):
    pass

for i in file產生一個str ,所以你不能只for i, j, k in filefor i, j, k in file並分三批讀取它(嘗試a, b, c = 'bar'a, b, c = 'too many characters'並查看a,b和c的值,以找出為什么你得到“太多的值來解壓”)。

目前還不清楚你的意思,但是如果你為每一行做同樣的事情而只是想在某個時刻停下來,那么就這樣做:

for line in file_handle:
    do_something(line)
    if some_condition:
        break  # Don't want to read anything else

(另外,不要將file用作變量名,而是要對內置函數進行着色。)

如果您正在做同樣的事情,為什么每次迭代需要處理多行?

對於文件行是你的朋友。 在io性能和內存方面,它通常比手動讀取文件更有效。

您對數據的行/格式的長度有所了解嗎? 如果是這樣,您可以讀取前n個字節(例如80 * 3)和f.read(240).split(“\\ n”)[0:3]。

如果您希望能夠反復使用此數據,可能需要采取以下措施:

lines = []
for line in file_handle:
    lines.append(line)

這將為您提供行列表,然后您可以通過索引訪問這些行。 此外,當你說一個巨大的文件時,它的大小很可能是微不足道的,因為python可以非常快速地處理數千行。

為什么你不能這樣做:

ctr = 0

對於文件中的行:

  if ctr == 0:

     ....

  elif ctr == 1:

     ....

  ctr = ctr + 1

如果你發現if / elif構造很難看,你可以創建一個哈希表或函數指針列表,然后執行:

對於文件中的行:

   function_list[ctr]()

或類似的東西

聽起來你正試圖從磁盤並行讀取......這真的很難做到。 給予您的所有解決方案都是現實和合法的。 你不應該因為代碼“看起來很難看”而讓某些事情讓你失望。 最重要的是它是多么高效/有效,那么如果代碼混亂,你可以整理它,但不要尋找一種全新的做法,因為你不喜歡一種方法在代碼中看起來像。

至於耗盡內存,你可能想看看泡菜

巧妙地使用zip功能可以做到這一點。 它很短,但有點巫術 - 我的口味(很難看出它是如何工作的)。 它會切斷最后一些不填充組的行,這可能是好的還是壞的,這取決於你正在做什么。 如果你需要最后一行, itertools.izip_longest可能會做到這一點。

zip(*[iter(inputfile)] * 3)

更明確,更靈活地進行,這是對Mats Ekberg解決方案的修改:

def groupsoflines(f, n):
    while True:
        group = []
        for i in range(n):
            try:
                group.append(next(f))
            except StopIteration:
                if group:
                    tofill = n - len(group)
                    yield group + [None] * tofill
                return
        yield group

for line1, line2, line3 in groupsoflines(inputfile, 3):
    ...

注意如果組中途的線條用完了,它將用None填充間隙,這樣你仍然可以解壓縮它。 因此,如果文件中的行數可能不是三的倍數,則需要檢查line2line3是否為None

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM