2014-12-03 3 views
3

파이썬의 빌트인 csv 모듈에서 이전에 눈치 채지 못한 동작이 나타났습니다. 일반적으로 CSV 파일을 읽을 때 doc's 다음과 같이 'with'를 사용하여 파일을 열고 'for'루프를 사용하여 판독기 객체를 반복합니다. 그러나 최근에는 두 번째 'for'루프가 아무 것도하지 않았다는 것을 알아 내기 위해 csv.reader 객체를 두 번 반복하여 반복적으로 시도했습니다.파이썬의 csv.reader 객체를 이해하지 못합니다.

import csv 

with open('smallfriends.csv','rU') as csvfile: 
readit = csv.reader(csvfile,delimiter=',') 

for line in readit: 
    print line 

for line in readit: 
    print 'foo' 

콘솔 출력 :

Austins-iMac:Desktop austin$ python -i amy.py 
['Amy', 'James', 'Nathan', 'Sara', 'Kayley', 'Alexis'] 
['James', 'Nathan', 'Tristan', 'Miles', 'Amy', 'Dave'] 
['Nathan', 'Amy', 'James', 'Tristan', 'Will', 'Zoey'] 
['Kayley', 'Amy', 'Alexis', 'Mikey', 'Sara', 'Baxter'] 
>>> 
>>> readit 
<_csv.reader object at 0x1023fa3d0> 
>>> 

그래서 'for'루프 두 번째는 기본적으로 아무것도하지 않습니다. 한 가지 생각은 csv.reader 객체가 한 번 읽은 후에 메모리에서 해제된다는 것입니다. 메모리 주소가 여전히 유지되므로이 경우가 아닙니다. 비슷한 문제가있는 post을 발견했습니다. 그들이 제공 한 이유는 일단 객체가 읽혀지면 포인터 스테이는 객체에 데이터를 쓸 준비가 된 메모리 주소의 끝에 있다는 것입니다. 이 올바른지? 누군가 여기서 일어나는 일에 대해 더 자세히 설명해 줄 수 있을까요? 그것을 다시 읽으려면 메모리 주소의 시작 부분에 포인터를 다시 밀어 넣는 방법이 있습니까? 나는 그것을하는 것이 나쁜 코딩 습관이라는 것을 알고 있지만, 나는 단지 궁금해서 파이썬의 두포 (hood)에서 일어나는 일에 대해 더 많이 배우고 싶다.

감사합니다. 너무 많은 데이터가 아닌 경우

+1

일단 반복기를 사용하면 첫 번째 루프에서 'readit'이 발생하지만 기본적으로는 비어 있습니다. – monkut

+0

그러면 "읽기 - 한 번"으로 생각할 수 있습니까? –

+1

예, 독자 객체는 생성자 객체와 비슷합니다 (요청한대로 (next()를 통해) 파일에서 행을 가져 와서 파싱합니다. 일단 그것을 소비하면 (전체 파일을 실행) 처음에 파일을 다시 시작하거나 다시 처리하려는 경우 모든 데이터를 메모리로 읽어야합니다. – monkut

답변

3

내가 reset() 또는 seek(0) 도움이 될 어떤 독자가하고있는 이유에 대해 다른 질문에 대한 답변을하려고합니다. 가장 기본적인 형태에서, CSV 리더는 다음과 같이 보일 수 있습니다

입니다
def csv_reader(it): 
    for line in it: 
     yield line.strip().split(',') 

는, 어떤 반복자 생산 문자열을 소요하고 당신에게 발전기를 제공합니다. 반복기에서 항목을 가져 와서 처리하고 항목을 반환하는 것뿐입니다. it이 사용되면 csv_reader가 종료됩니다. 독자는 iterator가 어디에서 왔는지 또는 제대로 반복하는 방법을 모르고 있기 때문에 자체 재설정을 시도하지도 않습니다. 그것은 프로그래머에게 맡겨져 있습니다.

판독기를 모르거나 새 판독기를 만들지 않고도 반복기를 수정할 수 있습니다. 나의 요점을 보여주는 몇 가지 예가있다.

data = open('data.csv', 'r') 
reader = csv.reader(data) 

print(next(reader))    # Parse the first line 
[next(data) for _ in range(5)] # Skip the next 5 lines on the underlying iterator 
print(next(reader))    # This will be the 7'th line in data 
print(reader.line_num)   # reader thinks this is the 2nd line 
data.seek(0)      # Go back to the beginning of the file 
print(next(reader))    # gives first line again 

data = ['1,2,3', '4,5,6', '7,8,9'] 
reader = csv.reader(data)   # works fine on lists of strings too 
print(next(reader))    # ['1', '2', '3'] 

일반적으로 2 단계가 필요한 경우 파일을 닫거나 다시 열고 새로운 csv 리더를 사용하는 것이 가장 좋습니다. 깨끗하고 좋은 부기를 보장합니다.

0

, 당신은 항상리스트에 읽을 수 있습니다 :

import csv 

with open('smallfriends.csv','rU') as csvfile: 
    readit = csv.reader(csvfile,delimiter=',') 
    csvdata = list(readit) 

    for line in csvdata : 
     print line 

    for line in csvdata : 
     print 'foo' 
+0

그래, 그게 항상 옵션이지만, 나는 더 낮은 수준에서 일어나는 일과 왜 객체가 두 번에 걸쳐 반복 될 수 없는지에 더 관심이있다. –

1

순회을 단순히 기본 파일 객체의 선 반복 래핑 csvreader 이상. 각 반복에서 독자는 파일에서 다음 줄을 가져 와서 변환하고 반환합니다.

따라서 csvreader를 반복하는 것은 iterating over files과 동일한 규칙을 따릅니다. 즉, 파일이 끝나면 두 번째 반복 전에 시작 부분을 찾아야합니다.

의 I 그것을 테스트하지 않았습니다하지만 아래 수행해야합니다

import csv 

with open('smallfriends.csv','rU') as csvfile: 
    readit = csv.reader(csvfile,delimiter=',') 

    for line in readit: 
     print line 

    # go back to the start of the file 
    csvfile.seek(0) 

    for line in readit: 
     print 'foo 
관련 문제