http로 파일을 땡겨올 때, 스트리밍으로 처리하고 싶을 때가 있다. 예를 들어 가져오는 파일이 겁나 크다면, 그걸 다 파일로 저장하고 나서 처리하거나, 메모리에 때려넣고 처리하거나 여튼 문제다. 멀티쓰레드 걸고 하면 메모리 문제도 그렇고 tempfile 쓰는 것도 다 받고 나서 처리해야 하고 뭐 그렇다. iter_lines()로 간단히 해결되는데, 스택 오버 플로우고 뭐고 파이썬이 php와는 결이 다르다고는 하나, 쉽다는 이유 하나로 phpschool화 되어가는 것은 아닌지 이제 정답을 찾기가 꽤 어렵다.
아래 코드는 방금 짠 테스트 코드인데, csv 파싱을 위해 csv 모듈을 일일히 콜하고 있다는 불합리성은 일단 제껴두고-_- iter_lines만 보면 된다. 관측결과 실제로도 http 응답을 받으면서 바로바로 처리하고 있다. (http chunked 참조)
def get_url_csv(self):
debug_log('csv 다운로드 시작 : ', self.dbg)
url = self.metas['url'].split('?')
res = requests.get(url[0], stream=True, params=url[1], proxies=proxyDict)
if res.status_code != 200:
debug_log('csv 다운로드 실패 : ', self.dbg)
exit(-1)
first = True
count = 0
for r in res.iter_lines(chunk_size=4096):
line = list(csv.reader([r], delimiter = ','))[0]
if first:
first = False
fields_idx = self.get_field_idx(line)
continue
out = self.parse_func(line, fields_idx)
if out is not None:
print out
count += 1
debug_log('csv 다운로드 라인 : ', str(self.metas['lines_exported']) + ' / ' + self.dbg)
debug_log('csv 처리 라인 : ', str(count) + ' / ' + self.dbg)
if self.metas['lines_exported'] != count:
debug_log('[WARN] csv 처리 라인 불일치!!!! : ', self.dbg)
res.connection.close()