🇯🇵 日本語 | 🇺🇸 English | 🇪🇸 Español | 🇵🇹 Português | 🇹🇭 ไทย | 🇨🇳 中文

[Python] คู่มือฉบับสมบูรณ์สำหรับโมดูล csv! อธิบายจุดที่มือใหม่มักติดปัญหาในการอ่านและเขียนไฟล์ CSV

หากต้องการเรียกใช้ Python ผ่าน Command Prompt หรือ PowerShell บนคอมพิวเตอร์ของคุณ คุณจำเป็นต้องดาวน์โหลดและติดตั้ง Python ก่อน
หากคุณยังไม่ได้ติดตั้ง กรุณาดูบทความ การติดตั้ง Python และการตั้งค่าสภาพแวดล้อมการพัฒนา เพื่อทำการติดตั้ง Python

"อยากจะจัดการไฟล์ CSV ในการเขียนโปรแกรม แต่ไม่รู้จะเริ่มจากตรงไหนดี..."

สวัสดีครับ! ผมคือผู้ดูแลเว็บไซต์นี้ ซึ่งเมื่อไม่กี่เดือนก่อนก็ยังเป็น "อดีต" มือใหม่เหมือนกับทุกท่านครับ จากประสบการณ์ที่สร้างเว็บไซต์ 2 แห่งด้วยตัวเองในเวลาหนึ่งเดือนครึ่งโดยอาศัยพลังของ AI ผมขอบอกเลยว่า การจัดการไฟล์ CSV เป็นทักษะที่หลีกเลี่ยงไม่ได้ในการพัฒนาเว็บ และยังมีประโยชน์อย่างยิ่งอีกด้วย!

จริงๆ แล้ว ความรู้เรื่อง CSV นี้ช่วยผมได้มากเลยครับ ตอนที่สร้างฟังก์ชันสำหรับจัดการข้อมูลจากฟอร์มติดต่อสอบถาม หรืออัปโหลดรายการสินค้าจำนวนมาก

ในบทความนี้ ผมจะใช้ประสบการณ์จริง (และเรื่องราวความล้มเหลวมากมาย...) มาอธิบายวิธีการอ่านและเขียนไฟล์ CSV ได้อย่างอิสระโดยใช้โมดูล `csv` ของ Python ให้เข้าใจง่ายที่สุดในโลกครับ ผมจะพยายามใช้ศัพท์เทคนิคน้อยที่สุด เมื่อคุณอ่านบทความนี้จบ คุณจะกลายเป็นผู้เชี่ยวชาญด้าน CSV อย่างแน่นอนครับ!


วอร์มอัพ: มาเตรียมไฟล์ CSV ตัวอย่างกันเถอะ

ก่อนอื่น มาเตรียมไฟล์ CSV ที่จะใช้ฝึกฝนกันครับ คัดลอกเนื้อหาด้านล่างนี้แล้วบันทึกในคอมพิวเตอร์ของคุณด้วยชื่อ `members.csv` นะครับ จุดสำคัญคือต้องบันทึกด้วยการเข้ารหัส (Encoding) แบบ UTF-8 (ตอนที่บันทึกในโปรแกรม Notepad จะมีตัวเลือกให้เลือกการเข้ารหัสครับ)

ไฟล์นี้จำลองมาจากรายชื่อสมาชิกของเว็บไซต์สมมติแห่งหนึ่งครับ

id,name,email
1,สมชาย ใจดี,somchai.jaidee@example.com
2,สมศรี มีสุข,somsri.meesuk@example.com
3,มานะ พากเพียร,mana.pakpian@example.com

พื้นฐาน: มาลองอ่านไฟล์ CSV กัน (`csv.reader`)

สิ่งแรกที่ต้องทำคือการอ่านเนื้อหาของไฟล์ CSV ด้วย Python ครับ เราจะมาลองอ่านไฟล์ `members.csv` ที่สร้างไว้เมื่อสักครู่ แล้วแสดงผลในคอนโซลกัน

นี่คือโค้ดสรุปครับ! ลองคัดลอกไปรันดูได้เลย วิธีที่ง่ายที่สุดคือสร้างไฟล์ Python ไว้ในโฟลเดอร์เดียวกับ `members.csv` แล้วรันครับ

<!-- โค้ด Python ที่ผ่านการ escape สำหรับ HTML -->
import csv

# --- จุดที่ผมติดปัญหาข้อที่ 1: ต้องระบุการเข้ารหัสตัวอักษรเสมอ! ---
# ใน Windows ถ้าไม่ระบุอะไรเลย บางครั้งมันจะพยายามเปิดด้วย Shift_JIS
# และทำให้เกิดข้อผิดพลาดได้
# ดังนั้นควรใส่ `encoding='utf-8'` ไว้เหมือนเป็นเครื่องรางเลยครับ
with open('members.csv', mode='r', encoding='utf-8') as f:
    
    # เมื่อส่งไฟล์ไปให้ csv.reader จะได้อ็อบเจกต์ reader ที่ช่วยแยกวิเคราะห์ CSV กลับมา
    reader = csv.reader(f)
    
    # สามารถวนลูปจัดการทีละบรรทัดได้
    for row in reader:
        print(row)

# ผลลัพธ์การทำงาน:
# ['id', 'name', 'email']
# ['1', 'สมชาย ใจดี', 'somchai.jaidee@example.com']
# ['2', 'สมศรี มีสุข', 'somsri.meesuk@example.com']
# ['3', 'มานะ พากเพียร', 'mana.pakpian@example.com']

เป็นยังไงบ้างครับ? เนื้อหาของ CSV แสดงขึ้นมาในเทอร์มินัลของคุณหรือยังครับ?
จุดที่น่าสนใจคือข้อมูล 1 บรรทัดจะถูกดึงออกมาเป็น list (ไอ้ที่อยู่ในวงเล็บ `[]` น่ะครับ) หนึ่งอัน ข้อมูลที่คั่นด้วยจุลภาคอย่าง `['1', 'สมชาย ใจดี', 'somchai.jaidee@example.com']` ก็จะกลายเป็นสมาชิกแต่ละตัวในลิสต์ครับ

อธิบายเพิ่มเติม: `with open(...) as f:` คืออะไร?
นี่เป็น "ธรรมเนียมปฏิบัติ" เวลาจัดการกับไฟล์ครับ การเขียนแบบนี้จะทำให้ Python ปิดไฟล์ให้เราโดยอัตโนมัติเมื่อจบการทำงานในบล็อก `with` การลืมปิดไฟล์อาจนำไปสู่ปัญหาที่ไม่คาดคิดอย่าง Memory Leak ได้ ดังนั้นเราควรใช้ `with` เสมอครับ!

[เรื่องเล่าความล้มเหลวของผม #1] นรกของตัวอักษรเพี้ยนกับ `encoding`

ตอนที่ผมทำแบบนี้ครั้งแรก โดยเฉพาะบน PC ที่ใช้ Windows คอนโซลของผมเต็มไปด้วยสัญลักษณ์ที่อ่านไม่ออก (ที่เรียกกันว่า "ตัวหนังสือเต้าหู้") เลยครับ สาเหตุก็คือ การเข้ารหัสตัวอักษร (character encoding) คอมพิวเตอร์จะไม่สามารถอ่านไฟล์ได้อย่างถูกต้องถ้าเราไม่บอกมันว่าไฟล์นั้นเขียนด้วยกฎของภาษา (encoding) แบบไหน

วิธีแก้คือการเพิ่ม `encoding='utf-8'` เข้าไปในอาร์กิวเมนต์ของ `open()` ครับ `UTF-8` เป็นมาตรฐานการเข้ารหัสตัวอักษรสากล ซึ่งถ้าใช้ตัวนี้ส่วนใหญ่ก็จะไม่มีปัญหาครับ เป็นความรู้ที่จำเป็นในโลกของเว็บ ดังนั้นทำให้เป็นนิสัยไว้เลยครับ!


พื้นฐาน (ต่อ): มาลองเขียนไฟล์ CSV ใหม่กัน (`csv.writer`)

ต่อไปคือการเขียนข้อมูลครับ เราจะมาลองบันทึกข้อมูลลิสต์ที่สร้างด้วย Python ให้เป็นไฟล์ CSV ใหม่กันดู ตัวอย่างเช่น การเขียนข้อมูลสมาชิกใหม่ลงในไฟล์ `new_members.csv` ครับ

<!-- โค้ด Python ที่ผ่านการ escape สำหรับ HTML -->
import csv

# ข้อมูลที่ต้องการเขียน (ลิสต์ซ้อนลิสต์)
new_data = [
    ['4', 'วิชัย รักไทย', 'wichai.rakthai@example.com'],
    ['5', 'อรุณี ศรีงาม', 'arunee.sringam@example.com']
]

# --- จุดที่ผมติดปัญหาข้อที่ 2: บรรทัดว่างปริศนา แก้ได้ด้วย newline='' ---
# mode='w' คือโหมดเขียน ถ้าไม่มีไฟล์อยู่จะสร้างใหม่
# ถ้าไม่ระบุ newline='' ใน Windows จะเกิดบรรทัดว่างแทรกทุกๆ บรรทัด!
with open('new_members.csv', mode='w', encoding='utf-8', newline='') as f:
    
    writer = csv.writer(f)
    
    # ถ้าต้องการเขียนแค่บรรทัดเดียว ใช้ writerow
    writer.writerow(['id', 'name', 'email']) # บรรทัดหัวเรื่อง (Header)
    
    # ถ้าต้องการเขียนหลายบรรทัดพร้อมกัน ใช้ writerows
    writer.writerows(new_data)

print('สร้างไฟล์ new_members.csv เรียบร้อยแล้ว!')

เมื่อรันโค้ดนี้ จะมีไฟล์ชื่อ `new_members.csv` ถูกสร้างขึ้นมาในโฟลเดอร์เดียวกันครับ ลองเปิดดูสิครับ ข้อมูลถูกเขียนลงไปอย่างถูกต้องใช่ไหมล่ะครับ?

[เรื่องเล่าความล้มเหลวของผม #2] นายเป็นใครกัน!? บรรทัดว่างปริศนากับ `newline=''`

นี่ก็เป็นอีกปัญหาที่ผมเสียเวลาไปครึ่งวันเลยครับ ลองลบ `newline=''` ออกจากโค้ดด้านบนแล้วรันบน Windows ดูสิครับ เป็นยังไงบ้าง? ไฟล์ CSV ของคุณเต็มไปด้วยบรรทัดว่างที่น่ารำคาญแทรกอยู่ทุกบรรทัดใช่ไหมครับ?

นี่เป็นกับดักที่เจอบ่อย ซึ่งเกิดจากความแตกต่างในการจัดการรหัสขึ้นบรรทัดใหม่ของแต่ละ OS ครับ ผมจะขอข้ามคำอธิบายยาวๆ ไปนะครับ (ผมเองก็ถาม AI แล้วก็ได้แต่แบบ "อ๋อ เข้าใจ แต่ก็ไม่เข้าใจ!") แต่วิธีแก้มีเพียงหนึ่งเดียว

เวลาจะเขียนไฟล์ CSV ต้องใส่ `newline=''` ใน `open()` เสมอ!

นี่เป็นธรรมเนียมปฏิบัติที่สำคัญมาก ขนาดที่ในเอกสารทางการของ Python ยังเขียนไว้เลยว่า "ถ้าใช้โมดูล csv ควรระบุเสมอ" ท่องจำไว้เหมือนคาถาเลยครับ


ขั้นสูง #1: จัดการด้วย Dictionary ทำให้โค้ดอ่านง่ายขึ้นระดับเทพ (`DictReader` & `DictWriter`)

ถ้าใช้ `reader` แบบพื้นฐาน เราจะต้องจัดการข้อมูลด้วยหมายเลขดัชนี เช่น `row[1]` หรือ `row[2]` ซึ่งถ้ามีคอลัมน์เยอะๆ ก็จะเริ่มงงว่า "เอ๊ะ อีเมลนี่ดัชนีที่เท่าไหร่นะ...?" ใช่ไหมครับ

และแล้ว `DictReader` ก็ปรากฏตัว! เมื่อใช้ตัวนี้ เราจะได้ข้อมูลหนึ่งบรรทัดมาในรูปแบบ "dictionary" ครับ ซึ่งหมายความว่าเราจะสามารถเข้าถึงข้อมูลด้วยชื่อหัวเรื่อง (header) ได้ เช่น `row['name']` หรือ `row['email']` อัจฉริยะไปเลยไหมล่ะครับ?

การอ่าน: `DictReader`

<!-- โค้ด Python ที่ผ่านการ escape สำหรับ HTML -->
import csv

with open('members.csv', mode='r', encoding='utf-8') as f:
    # แค่ใช้ DictReader! ง่ายมาก!
    reader = csv.DictReader(f)
    
    for row in reader:
        # เข้าถึงชื่อด้วยคีย์ 'name' และอีเมลด้วยคีย์ 'email' ได้เลย!
        print(f"ชื่อ: {row['name']}, อีเมล: {row['email']}")

# ผลลัพธ์การทำงาน:
# ชื่อ: สมชาย ใจดี, อีเมล: somchai.jaidee@example.com
# ชื่อ: สมศรี มีสุข, อีเมล: somsri.meesuk@example.com
# ชื่อ: มานะ พากเพียร, อีเมล: mana.pakpian@example.com

เป็นไงครับ? `row['name']` อ่านเข้าใจง่ายกว่า `row[1]` แบบเทียบไม่ติดเลยใช่ไหมครับ! แบบนี้ต่อให้กลับมาดูโค้ดทีหลังก็รู้ได้ทันทีว่ากำลังทำอะไรอยู่

การเขียน: `DictWriter`

เมื่ออ่านเป็น dictionary ได้แล้ว ก็ต้องอยากเขียนเป็น dictionary ด้วยใช่ไหมครับ แน่นอนว่ามี `DictWriter` อยู่ครับ แค่เตรียมลิสต์ของ dictionary ไว้ ก็สามารถเขียนลง CSV ได้เลย

<!-- โค้ด Python ที่ผ่านการ escape สำหรับ HTML -->
import csv

# เตรียมข้อมูลเป็นลิสต์ของ dictionary
dict_data = [
    {'id': '6', 'name': 'สมศักดิ์ สามารถ', 'email': 'somsak.samart@example.com'},
    {'id': '7', 'name': 'นารีรัตน์ งามตา', 'email': 'nareerat.ngamta@example.com'}
]

# ลิสต์ของหัวเรื่อง (สำคัญ!)
fieldnames = ['id', 'name', 'email']

with open('dict_members.csv', mode='w', encoding='utf-8', newline='') as f:
    # ส่งไฟล์และหัวเรื่อง (fieldnames) ไปให้ DictWriter
    writer = csv.DictWriter(f, fieldnames=fieldnames)
    
    # อย่าลืมเขียนหัวเรื่องก่อนเป็นอันดับแรก!
    writer.writeheader()
    
    # เขียนลิสต์ของ dictionary ทั้งหมดในครั้งเดียว
    writer.writerows(dict_data)

print('สร้างไฟล์ dict_members.csv เรียบร้อยแล้ว!')

ข้อควรระวังในการใช้ `DictWriter` มี 2 ข้อครับ:

  1. ตอนที่สร้าง `csv.DictWriter()` ต้องส่ง `fieldnames` (ลิสต์ของหัวเรื่อง) เข้าไปด้วย
  2. ก่อนที่จะเขียนข้อมูล ต้องเขียนบรรทัดหัวเรื่องด้วย `writer.writeheader()` ก่อน

ถ้าลืมสองข้อนี้จะเขียนข้อมูลได้ไม่ถูกต้อง ระวังด้วยนะครับ! (แน่นอนว่าผมก็เคยพลาดมาแล้ว)


ขั้นสูง #2: การเพิ่มข้อมูลต่อท้ายไฟล์ CSV ที่มีอยู่

"อยากจะเพิ่มข้อมูลสมาชิกใหม่เข้าไปในลิสต์ทุกครั้งที่มีคนส่งฟอร์มติดต่อเข้ามา" ในกรณีแบบนี้ เราจะเปิดไฟล์ใน "โหมดเพิ่มข้อมูลต่อท้าย" (append mode) ครับ

วิธีทำง่ายสุดๆ แค่เปลี่ยน `mode` ใน `open()` จาก `'w'` (write) เป็น `'a'` (append) เท่านั้นเองครับ

<!-- โค้ด Python ที่ผ่านการ escape สำหรับ HTML -->
import csv

# ข้อมูลสมาชิกใหม่ที่ต้องการเพิ่ม
new_member = ['8', 'ปรีชา ชาญชัย', 'preecha.chanchai@example.com']

# แค่เปลี่ยนโหมดเป็น 'a' (append) เท่านั้น!
# เนื่องจากเป็นการเพิ่มข้อมูล อย่าลืมใส่ newline='' และ encoding='utf-8' ด้วยนะครับ
with open('members.csv', mode='a', encoding='utf-8', newline='') as f:
    writer = csv.writer(f)
    writer.writerow(new_member)

print('เพิ่มข้อมูลต่อท้ายไฟล์ members.csv เรียบร้อยแล้ว!')

หลังจากรันโค้ดนี้แล้ว ลองเปิดไฟล์ `members.csv` ดูอีกครั้งครับ จะเห็นว่าข้อมูลของคุณปรีชาถูกเพิ่มเข้าไปที่บรรทัดสุดท้ายแล้ว ถ้าจะเพิ่มข้อมูลด้วย `DictWriter` ก็ระวังอย่าไปเรียกใช้ `writeheader()` นะครับ ไม่งั้นหัวเรื่องจะถูกเพิ่มเข้าไปทุกครั้งที่เพิ่มข้อมูล


[สัมผัสประสบการณ์จริง] มาลองเล่นกับ CSV บนเบราว์เซอร์กัน!

เอาล่ะครับ เราดูโค้ดกันมาเยอะแล้ว แต่ท้ายที่สุดแล้ว การได้ลองรันและปรับแก้ด้วยตัวเองคือทางลัดที่ดีที่สุดครับ

ดังนั้นในครั้งนี้ ผมได้เตรียมเดโมแบบอินเทอร์แอคทีฟที่สามารถจัดการข้อมูล CSV ได้แบบเรียลไทม์ โดยใช้ "PyScript" ซึ่งเป็นเทคโนโลยีสุดมหัศจรรย์ที่ทำให้รัน Python บนเบราว์เซอร์ได้ มาให้ลองเล่นกันครับ!

คัดลอกโค้ด HTML ทั้งหมดด้านล่างนี้ไปบันทึกใน PC ของคุณด้วยชื่ออย่าง `csv_test.html` แล้วเปิดไฟล์นั้นด้วยเว็บเบราว์เซอร์ดูครับ เพียงเท่านี้เบราว์เซอร์ของคุณก็จะกลายเป็นโปรแกรมแก้ไข CSV ในทันที!

<!-- โค้ด HTML ที่ผ่านการ escape สำหรับ HTML -->
<!DOCTYPE html>
<html lang="th">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>เดโมทดลองโมดูล CSV ของ Python</title>
    <!-- การโหลด PyScript -->
    <link rel="stylesheet" href="https://pyscript.net/releases/2024.1.1/core.css" />
    <script type="module" src="https://pyscript.net/releases/2024.1.1/core.js"></script>
    <!-- สไตล์แบบง่ายๆ -->
    <style>
        body { font-family: sans-serif; background-color: #202124; color: #e8eaed; padding: 2em; line-height: 1.6; }
        h1, h2 { color: #8ab4f8; }
        textarea, button {
            border: 1px solid #5f6368;
            background-color: #3c4043;
            color: #e8eaed;
            border-radius: 4px;
            padding: 0.5em 1em;
        }
        textarea { width: 100%; height: 150px; margin-bottom: 1em; font-family: monospace; }
        button { cursor: pointer; margin-right: 1em; }
        button:hover { background-color: #5f6368; }
        table { border-collapse: collapse; width: 100%; margin-top: 1em; }
        th, td { border: 1px solid #5f6368; padding: 8px; text-align: left; }
        th { background-color: #3c4043; }
        pre { background-color: #1e1e1e; padding: 1em; border-radius: 4px; white-space: pre-wrap; }
    </style>
</head>
<body>
    <h1>ทดลองใช้โมดูล CSV ของ Python บนเบราว์เซอร์!</h1>
    <p>ป้อนหรือแก้ไขข้อมูล CSV ในช่องข้อความด้านล่าง แล้วกดปุ่ม "โหลด CSV และแสดงเป็นตาราง"</p>

    <textarea id="csv-input">ชื่อ,อายุ,เมือง
สมชาย ใจดี,32,โตเกียว
สมศรี มีสุข,28,โอซาก้า
มานะ พากเพียร,45,ฟุกุโอกะ</textarea>

    <button py-click="read_csv">โหลด CSV และแสดงเป็นตาราง</button>

    <h2>ผลลัพธ์การโหลด</h2>
    <div id="table-output"></div>

    <py-script>
# โค้ด Python ด้านล่างนี้ทำงานบนเบราว์เซอร์ครับ
import csv
import io # โมดูลสำหรับจัดการสตริงเหมือนเป็นไฟล์
from pyscript import document

def read_csv(*args, **kwargs):
    # ดึงข้อมูล CSV จากช่องข้อความ
    csv_data = document.querySelector("#csv-input").value
    
    # ใช้ io.StringIO เพื่อจัดการสตริงเหมือนเป็นไฟล์
    # ทำให้สามารถใช้โมดูล csv ได้เหมือนกับการอ่านจากไฟล์จริงๆ
    csv_file = io.StringIO(csv_data)
    
    # อ่านด้วย csv.reader
    reader = csv.reader(csv_file)
    
    # สร้างตาราง HTML
    html = "<table>"
    try:
        # ประมวลผลบรรทัดแรก (หัวเรื่อง)
        header = next(reader)
        html += "<thead><tr>"
        for col in header:
            html += f"<th>{col}</th>"
        html += "</tr></thead>"
        
        # ประมวลผลบรรทัดที่สองเป็นต้นไป (ข้อมูล)
        html += "<tbody>"
        for row in reader:
            html += "<tr>"
            for cell in row:
                html += f"<td>{cell}</td>"
            html += "</tr>"
        html += "</tbody>"
    except StopIteration:
        # การจัดการกรณีที่ไม่มีข้อมูล
        html += "<tr><td>ไม่มีข้อมูล</td></tr>"

    html += "</table>"
    
    # แสดงผลลัพธ์ในองค์ประกอบ DIV
    output_div = document.querySelector("#table-output")
    output_div.innerHTML = html
    </py-script>
</body>
</html>

ลองแก้ไขเนื้อหาในช่องข้อความแล้วกดปุ่มดูสิครับ จะเห็นว่าข้อความที่คั่นด้วยจุลภาคถูกแปลงเป็นตารางสวยงาม นี่แหละครับคือพลังของโมดูล `csv`! เชิญทดลองเล่นได้ตามสบายเลยครับ


สรุป: ตอนนี้คุณเป็นมาสเตอร์ CSV แล้ว!

お疲れ様でした!長旅でしたが、これであなたはPythonを使ったCSV操作の基本から応用まで、完全にマスターしました。最後に、今日学んだ最重要ポイントを振り返っておきましょう。

แค่จำประเด็นเหล่านี้ได้ ก็แทบจะไม่มีปัญหาในการจัดการ CSV ในการทำงานจริงแล้วครับ ไม่ว่าจะนำข้อมูลที่ดาวน์โหลดจากเว็บไซต์มาวิเคราะห์ หรือลงทะเบียนข้อมูลจำนวนมากเข้าระบบในครั้งเดียว ขอบเขตการใช้งานนั้นกว้างขวางไม่สิ้นสุด ขึ้นอยู่กับไอเดียของคุณเลยครับ

เคล็ดลับในการเก่งโปรแกรมมิ่งคือการสั่งสมประสบการณ์ความสำเร็จเล็กๆ น้อยๆ อย่าง "มันทำงานได้!" ไปเรื่อยๆ ทีละอย่างครับ หากบทความนี้เป็นส่วนหนึ่งที่ช่วยคุณในเรื่องนั้นได้ ผมก็ไม่มีอะไรจะดีใจไปกว่านี้อีกแล้วครับ

ก้าวต่อไป

รูปแบบข้อมูลที่ใช้บ่อยในการพัฒนาเว็บพอๆ กับ CSV ก็คือ "JSON" ครับ ซึ่งเป็นความรู้ที่จำเป็นสำหรับการพัฒนาที่ซับซ้อนขึ้น เช่น การเชื่อมต่อ API มาฝึกฝนให้เชี่ยวชาญในบทความถัดไปเพื่อยกระดับฝีมือกันเถอะครับ!

วิธีจัดการข้อมูล JSON ด้วยโมดูล json