2013-10-28 68 views
0

我打開了一個文件,並將其命名爲「myfile」;我想從它創建兩個不同的字典,但文件關閉我,我假設,因爲我在第一個循環中創建第一個字典。 我得到一個空字典的直方圖,我試過使用myfile作爲x和使用x而不是f爲第二個循環,我得到這個「ValueError:關閉文件上的I/O操作」。從文件創建兩個字典時保持文件打開

此外,我正在做一個類的函數,如果這有所作爲。

有沒有人知道一種方法來使這項工作?

d = {} 
    d2 ={} 
    with myfile as f: 
     next(f) 
     for line in f: 
      k, v = line.split() 
      d[int(k)] = int(v) 
      next(f) 

     for line in f: 
      items = line.split() 
      key, values = int(items[0]), items[1:] 
      d2.setdefault(key, []).extend(values) 


    hist = defaultdict(list) 
    for key, values in d2.iteritems(): 
     hist[len(values)].append(key) 
    histogram = dict(hist) 
+0

爲什麼你需要兩個循環?你不能只通過'f'循環一次嗎? – ForeverWintr

+0

您可以使用seek()將當前位置設置迴文件的開頭。 –

回答

4

你只是用盡了第一次循環遍歷迭代器。因此,當您嘗試循環時,沒有什麼可以看到的。

只要把你所有的邏輯放在同一個循環中。我不太確定你的循環應該做什麼,但它看起來像第一個循環,因爲它應該只適用於每個奇數(0索引)的行,這很容易用enumerate完成。第二個循環似乎適用於每一行,因此我將從該循環開始,然後向其添加「第一個」循環的功能;是這樣的:

with myfile as f: # Better: with open('/some/file.txt', 'rb') as f: 
    for i, line in enumerate(f): 
     # "Second" loop 
     items = line.split() 
     key, values = int(items[0]), items[1:] 
     d2.setdefault(key, []).extend(values) 

     # "First" loop 
     if i % 2 != 0: # Only process odd-numbered lines 
      k, v = items 
      d[int(k)] = int(v) 
+0

我添加了myfile.seek(0)在我的循環之間,它工作。 我想添加一個答案,但我沒有足夠的聲譽,所以我不能。 – user2926009

+0

@ user2926009這也可以工作,但如果你的文件很大或者你正在運行這麼多,你可能需要將代碼重構爲一個循環,以便運行得更快。 –

2

爲了解決這個問題,那麼你問的第一個循環

然而,@亨利 - keiter的建議,遍歷一次應該受到重視的數據後,調用f.seek(0)

1

我同意亨利:不要做seek(),除非你確實需要做一個兩遍算法。

你有沒有理由不能?

此外,在第一個循環中使用next(f)看起來很可疑:通常情況下,如果您要迭代某些內容,則不需要爲支持迭代的那件事做任何其他操作。

我期待像下面的內容:

with myfile as f: ## FIXME: this is suspect. 'myfile' is accessible outside this 
        ## `with` already, so there's something weird here. 
    for (index, line) in itertools.izip(itertools.count(), f): 
     if index % 2 == 1: 
      k, v = line.split() 
      d[int(k)] = int(v) 

     items = line.split() 
     key, values = int(items[0]), items[1:] 
     d2.setdefault(key, []).extend(values) 

在那裏你可以遍歷單傳過來的文件。原始代碼中的第一個循環似乎只關心文件中的奇數行,因此這種重寫試圖表達該想法。


另一方面:使用with這裏看起來不對。我們通常做,如果我們希望with接管資源的開啓和關閉的責任,以及with的身體內給它一個名字:

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

但是代碼編寫具有已經打開它。這意味着myfile變量在這裏被初始化,並且仍然可以在with之外訪問。

我們會做更多的正義的代碼,如果我們使用了try/finally,像這樣:

try: 
    ... ## use myfile here instead of f 
finally: 
    myfile.close() 

,其中代碼使更清晰該myfile將保證收於try/finally結束。