LabHub
배우기 러닝패스 코스

고객 데이터 다루기 · 규격을 안 지킨 CSV · 실습

행 수가 안 맞는다 — 줄이 아니라 레코드를 센다

LabHub 에서 이어서 보기

목표

고객 CSV 를 줄이 아니라 레코드로 세는 문지기 csvgate.py 를 만든다. 손으로 자른 파서와 표준 파서의 답이 얼마나 벌어지는지를 자기 자료로 재고, 구분자·줄 끝·머리글 유무를 판별하고, 못 쓰는 줄을 거절 파일로 떼어 낸다.

왜 중요한가

CSV 에서 줄과 레코드는 다른 것이다. 주문 메모에 줄바꿈이 있으면 레코드 하나가 파일에서 두 줄을 차지하고, 상호에 쉼표가 있으면 그 줄을 쉼표로 자를 때 칼럼이 늘어난다. 두 경우 모두 파서는 오류를 내지 않고 그럴듯한 숫자를 내놓는다. 그래서 이 실수는 고객이 숫자를 보고 이상하다고 말할 때까지 살아남는다.
RFC 4180 은 인용 규칙과 줄 끝을 정하지만, 규격을 다 지킨 파일만 오지는 않는다. 구분자가 세미콜론이거나 탭이고, 줄 끝이 한 파일 안에서 섞여 있고, 머리글이 없는 파일이 온다. 머리글이 있는지는 파일 안에 적혀 있지 않아서 판별해야 한다.
그리고 못 쓰는 줄을 어떻게 다룰지가 남는다. 조용히 건너뛰면 그 건수만큼 매출이 사라지고 설명할 근거가 없다. 은행 수신 파일이라면 한 줄만 어긋나도 파일을 통째로 돌려보내지만, 고객이 준 분석용 자료는 돌려보낼 곳이 없다 — 쓸 수 있는 줄은 쓰고 못 쓰는 줄만 떼어 낸다.
채점기는 여러분의 문구를 믿지 않는다. 임시 디렉터리에 채점기가 만든 피드를 차려 놓고 여러분의 문지기를 실제로 실행해 레코드 수·금액 합계·거절 사유를 채점기가 직접 센 값과 대조한다. 상호와 금액은 실행마다 바뀐다.

단계

1. /root/csv/gen_feed.py 를 만들어 실행해 /root/csv/feed 아래 일곱 파일을 만드세요. 같은 주문 20건이 일곱 가지 모양으로 나옵니다.
2. /root/csv/csvgate.pynaive 를 만들어 줄 하나를 레코드 하나로 믿는 파서의 답(rows·amount_total·bad_field_count)을 내게 하세요.
3. parse 를 더해 csv 모듈로 제대로 센 답(records·amount_total)을 내게 하고, 두 답의 차이를 /root/csv/gap.json 에 적으세요.
4. sniff 를 더해 줄 끝을 CRLF·LF·MIXED 로 판별하게 하세요.
5. sniff 가 구분자를 후보(쉼표·세미콜론·탭·파이프) 중에서 판별하게 하세요.
6. sniff 가 머리글 유무(header)와 칼럼 수(fields)를 판별하게 하세요.
7. check 를 더해 못 쓰는 줄을 사유별로 세고 거절 파일로 떼어 내게 하세요. 거절 파일은 입력 파일이 있는 디렉터리 아래 rejects/ 에 같은 이름으로 씁니다.
8. 피드 일곱 파일을 한 번에 처리해 /root/csv/feed_report.json/root/csv/feed_report.md 를 만드세요.

참고

단계 8개

  1. 일곱 가지 모양의 같은 피드 만들기
  2. 손으로 자른 파서의 답 내기
  3. 인용 안의 쉼표와 줄바꿈 제대로 읽기
  4. 줄 끝이 섞인 파일 가려내기
  5. 구분자를 후보 중에서 고르기
  6. 머리글이 있는지 없는지 판별하기
  7. 못 쓰는 줄만 떼어 내기
  8. 피드 한 장으로 보고하기