Python csv.Sniffer: เดารูปแบบไฟล์ได้ แต่ต้องมี fallback ที่คาดเดาได้
พี่โชว์Engineering
ไฟล์ที่ผู้ใช้เรียก CSV อาจคั่นด้วย comma, semicolon หรือ tab ครับ csv.Sniffer ดู sample แล้วคืน dialect ที่น่าจะใช่ ช่วยลดหน้าตั้งค่า แต่เอกสารย้ำว่าการเดา header และ dialect เป็น heuristic จึงอาจให้ผลบวกหรือลบผิด
import csv
import io
import unittest
def read_rows(text: str, fallback: str = ",") -> list[list[str]]:
sample = text[:4096]
try:
dialect = csv.Sniffer().sniff(sample, delimiters=",;\t")
except csv.Error:
dialect = csv.excel
dialect.delimiter = fallback
return list(csv.reader(io.StringIO(text), dialect))
class SnifferTests(unittest.TestCase):
def test_semicolon(self):
self.assertEqual(read_rows("name;score\nAda;9\n"), [["name", "score"], ["Ada", "9"]])
def test_ambiguous_sample_uses_fallback(self):
self.assertEqual(read_rows("single\n"), [["single"]])
if __name__ == "__main__":
unittest.main()
จำกัด delimiters ให้เหลือชุดที่ระบบรองรับจริง ไม่เช่นนั้นอักขระที่เกิดบ่อยในข้อความอาจถูกเดาเป็นตัวคั่น อ่าน sample แบบมีเพดานเพื่อไม่ให้ไฟล์ใหญ่กิน memory และอย่าถือ has_header() เป็นหลักฐาน schema ให้ validate จำนวนคอลัมน์ ชื่อ field และชนิดข้อมูลหลัง parse เสมอ
Recap
- จำกัด delimiter ที่ยอมรับ
- กำหนดขนาด sample และ fallback
- แยก “เดารูปแบบ” ออกจาก “ยืนยัน schema”
- ทดสอบไฟล์สั้น กำกวม และแถวคอลัมน์ไม่ครบ