csv --- CSV Đọc và ghi tệp¶
Source code: Lib/csv.py
Định dạng được gọi là CSV (Giá trị được phân tách bằng dấu phẩy) là định dạng nhập và xuất phổ biến nhất cho bảng tính và cơ sở dữ liệu. Định dạng CSV đã được sử dụng trong nhiều năm trước khi cố gắng mô tả định dạng này theo cách chuẩn hóa trong RFC 4180. Việc thiếu một tiêu chuẩn được xác định rõ ràng có nghĩa là những khác biệt nhỏ thường tồn tại trong dữ liệu được tạo ra và sử dụng bởi các ứng dụng khác nhau. Những khác biệt này có thể gây khó chịu khi xử lý tệp CSV từ nhiều nguồn. Tuy nhiên, mặc dù các dấu phân cách và ký tự trích dẫn khác nhau, định dạng tổng thể vẫn tương tự đến mức có thể viết một mô-đun duy nhất có thể thao tác dữ liệu đó một cách hiệu quả, ẩn các chi tiết đọc và ghi dữ liệu khỏi người lập trình.
Mô-đun csv triển khai các lớp để đọc và ghi dữ liệu dạng bảng ở định dạng CSV. Nó cho phép các lập trình viên nói, "ghi dữ liệu này ở định dạng mà Excel ưa thích" hoặc "đọc dữ liệu từ tệp này do Excel tạo ra" mà không biết chi tiết chính xác về định dạng CSV được Excel sử dụng. Các lập trình viên cũng có thể mô tả các định dạng CSV được các ứng dụng khác hiểu hoặc xác định các định dạng CSV cho mục đích đặc biệt của riêng họ.
Các đối tượng reader và writer của mô-đun csv đọc và ghi các chuỗi. Các lập trình viên cũng có thể đọc và ghi dữ liệu ở dạng từ điển bằng cách sử dụng các lớp DictReader và DictWriter.
Xem thêm
- PEP 305 - CSV Tập tin API
Đề xuất cải tiến Python đề xuất bổ sung này cho Python.
Nội dung mô-đun¶
Mô-đun csv xác định các chức năng sau:
- csv.reader(csvfile, /, dialect='excel', **fmtparams)¶
Trả về một reader object sẽ xử lý các dòng từ csvfile đã cho. Tệp csvfile phải là một chuỗi có thể lặp lại, mỗi chuỗi có định dạng csv do người đọc xác định. Tệp csvfile thường là một đối tượng hoặc danh sách giống như tệp. Nếu csvfile là một đối tượng tệp, nó sẽ được mở bằng
newline=''. [1] Một tham số dialect tùy chọn có thể được cung cấp để xác định một tập hợp các tham số cụ thể cho một phương ngữ CSV cụ thể. Nó có thể là một thể hiện của một lớp con của lớpDialecthoặc một trong các chuỗi được hàmlist_dialects()trả về. Các đối số từ khóa fmtparams tùy chọn khác có thể được cung cấp để ghi đè các tham số định dạng riêng lẻ trong phương ngữ hiện tại. Để biết chi tiết đầy đủ về các tham số định dạng và phương ngữ, hãy xem phần Các tham số phương ngữ và định dạng.Mỗi hàng đọc từ tệp csv sẽ được trả về dưới dạng danh sách các chuỗi. Không có chuyển đổi loại dữ liệu tự động nào được thực hiện trừ khi tùy chọn định dạng
QUOTE_NONNUMERICđược chỉ định (trong trường hợp đó các trường không trích dẫn sẽ được chuyển thành số float).Một ví dụ sử dụng ngắn:
>>> nhập csv >>> với open('eggs.csv', newline='') dưới dạng csvfile: ... spamreader = csv.reader(csvfile, delimiter=' ', quotechar='|') ... cho hàng trong spamreader: ... print(', '.join(row)) Thư rác, Thư rác, Thư rác, Thư rác, Thư rác, Đậu nướng Thư rác, Thư rác đáng yêu, Thư rác tuyệt vời
- csv.writer(csvfile, /, dialect='excel', **fmtparams)¶
Trả về đối tượng writer chịu trách nhiệm chuyển đổi dữ liệu của người dùng thành các chuỗi được phân tách trên đối tượng giống như tệp đã cho. csvfile có thể là bất kỳ đối tượng nào có phương thức
write(). Nếu csvfile là một đối tượng tệp, nó sẽ được mở bằngnewline=''[1]. Một tham số dialect tùy chọn có thể được cung cấp để xác định một tập hợp các tham số cụ thể cho một phương ngữ CSV cụ thể. Nó có thể là một thể hiện của một lớp con của lớpDialecthoặc một trong các chuỗi được hàmlist_dialects()trả về. Các đối số từ khóa fmtparams tùy chọn khác có thể được cung cấp để ghi đè các tham số định dạng riêng lẻ trong phương ngữ hiện tại. Để biết chi tiết đầy đủ về các phương ngữ và tham số định dạng, hãy xem phần Các tham số phương ngữ và định dạng. Để giúp giao tiếp với các mô-đun triển khai DB API dễ dàng nhất có thể, giá trịNoneđược viết dưới dạng chuỗi trống. Mặc dù đây không phải là một phép chuyển đổi có thể đảo ngược nhưng nó giúp chuyển các giá trị dữ liệu SQL NULL sang tệp CSV mà không cần xử lý trước dữ liệu được trả về từ lệnh gọicursor.fetch*. Tất cả dữ liệu không phải chuỗi khác đều được xâu chuỗi bằngstr()trước khi được ghi.Một ví dụ sử dụng ngắn:
nhập csv với open('eggs.csv', 'w', newline='') là csvfile: người viết thư rác = csv.writer(csvfile, delimiter=' ', quotechar='|', trích dẫn=csv.QUOTE_MINIMAL) spamwriter.writerow(['Spam'] * 5 + ['Đậu nướng']) spamwriter.writerow(['Thư rác', 'Thư rác đáng yêu', 'Thư rác tuyệt vời'])
- csv.register_dialect(name, /, dialect='excel', **fmtparams)¶
Liên kết dialect với name. name phải là một chuỗi. Phương ngữ có thể được chỉ định bằng cách chuyển một lớp con của
Dialecthoặc bằng các đối số từ khóa fmtparams hoặc cả hai, với các đối số từ khóa ghi đè các tham số của phương ngữ. Để biết chi tiết đầy đủ về các phương ngữ và tham số định dạng, hãy xem phần Các tham số phương ngữ và định dạng.
- csv.unregister_dialect(name)¶
Xóa phương ngữ được liên kết với name khỏi sổ đăng ký phương ngữ. Một
Errorđược nêu ra nếu name không phải là tên phương ngữ đã đăng ký.
- csv.get_dialect(name)¶
Trả về phương ngữ được liên kết với name. Một
Errorđược nêu ra nếu name không phải là tên phương ngữ đã đăng ký. Hàm này trả về mộtDialectbất biến.
- csv.list_dialects()¶
Trả lại tên của tất cả các phương ngữ đã đăng ký.
- csv.field_size_limit()¶
- csv.field_size_limit(new_limit)
Trả về kích thước trường tối đa hiện tại được trình phân tích cú pháp cho phép. Nếu new_limit được đưa ra, đây sẽ trở thành giới hạn mới.
Mô-đun csv xác định các lớp sau:
- class csv.DictReader(f, fieldnames=None, restkey=None, restval=None, dialect='excel', *args, **kwds)¶
Tạo một đối tượng hoạt động giống như một trình đọc thông thường nhưng ánh xạ thông tin trong mỗi hàng tới một
dictcó khóa được cung cấp bởi tham số fieldnames tùy chọn.Tham số fieldnames là sequence. Nếu fieldnames bị bỏ qua, các giá trị ở hàng đầu tiên của tệp f sẽ được sử dụng làm tên trường và sẽ bị loại bỏ khỏi kết quả. Nếu fieldnames được cung cấp, chúng sẽ được sử dụng và hàng đầu tiên sẽ được đưa vào kết quả. Bất kể tên trường được xác định như thế nào, từ điển vẫn giữ nguyên thứ tự ban đầu của chúng.
Nếu một hàng có nhiều trường hơn tên trường thì dữ liệu còn lại sẽ được đưa vào danh sách và được lưu trữ với tên trường được chỉ định bởi restkey (mặc định là
None). Nếu một hàng không trống có ít trường hơn tên trường thì các giá trị còn thiếu sẽ được điền bằng giá trị restval (mặc định làNone).Tất cả các đối số từ khóa hoặc tùy chọn khác được chuyển đến phiên bản
readercơ bản.Nếu đối số được truyền cho fieldnames là một iterator, thì nó sẽ bị ép buộc thành
list.Thay đổi trong phiên bản 3.6: Các hàng trả về hiện thuộc loại
OrderedDict.Thay đổi trong phiên bản 3.8: Các hàng trả về hiện thuộc loại
dict.Một ví dụ sử dụng ngắn:
>>> nhập csv >>> với open('names.csv', newline='') là csvfile: ... reader = csv.DictReader(csvfile) ... cho hàng trong trình đọc: ... print(row['first_name'], row['last_name']) ... Eric nhàn rỗi John Cleese >>> in (hàng) {'first_name': 'John', 'last_name': 'Cleese'}
- class csv.DictWriter(f, fieldnames, restval='', extrasaction='raise', dialect='excel', *args, **kwds)¶
Tạo một đối tượng hoạt động giống như một trình soạn thảo thông thường nhưng ánh xạ các từ điển vào các hàng đầu ra. Tham số fieldnames là một
sequencecác khóa xác định thứ tự các giá trị trong từ điển được truyền cho phương thứcwriterow()được ghi vào tệp f. Tham số restval tùy chọn chỉ định giá trị được ghi nếu từ điển thiếu khóa trong fieldnames. Nếu từ điển được truyền cho phương thứcwriterow()chứa khóa không được tìm thấy trong fieldnames, thì tham số extrasaction tùy chọn sẽ cho biết hành động cần thực hiện. Nếu nó được đặt thành'raise', giá trị mặc định,ValueErrorsẽ được nâng lên. Nếu nó được đặt thành'ignore', các giá trị bổ sung trong từ điển sẽ bị bỏ qua. Bất kỳ đối số từ khóa hoặc tùy chọn nào khác đều được chuyển đến phiên bảnwritercơ bản.Lưu ý rằng không giống như lớp
DictReader, tham số fieldnames của lớpDictWriterkhông phải là tùy chọn.Nếu đối số được truyền cho fieldnames là một iterator, thì nó sẽ bị ép buộc thành
list.Một ví dụ sử dụng ngắn:
nhập csv với open('names.csv', 'w', newline='') là csvfile: tên trường = ['first_name', 'last_name'] writer = csv.DictWriter(csvfile, fieldnames=fieldnames) nhà văn.writeheader() writer.writerow({'first_name': 'Baked', 'last_name': 'Beans'}) writer.writerow({'first_name': 'Đáng yêu', 'last_name': 'Spam'}) writer.writerow({'first_name': 'Tuyệt vời', 'last_name': 'Spam'})
- class csv.Dialect¶
Lớp
Dialectlà một lớp chứa có các thuộc tính chứa thông tin về cách xử lý dấu ngoặc kép, khoảng trắng, dấu phân cách, v.v. Do thiếu thông số kỹ thuật CSV nghiêm ngặt, các ứng dụng khác nhau sẽ tạo ra dữ liệu CSV khác nhau một cách tinh vi. Các phiên bảnDialectxác định cách hoạt động của các phiên bảnreadervàwriter.Tất cả các tên
Dialectcó sẵn đều được trả về bởilist_dialects()và chúng có thể được đăng ký với các lớpreadervàwritercụ thể thông qua các hàm khởi tạo (__init__) như sau:nhập csv với open('students.csv', 'w', newline='') là csvfile: nhà văn = csv.writer(csvfile, phương ngữ='unix')
- class csv.excel¶
Lớp
excelxác định các thuộc tính thông thường của tệp CSV do Excel tạo. Nó được đăng ký với tên phương ngữ'excel'.
- class csv.excel_tab¶
Lớp
excel_tabxác định các thuộc tính thông thường của tệp được phân tách bằng TAB do Excel tạo. Nó được đăng ký với tên phương ngữ'excel-tab'.
- class csv.unix_dialect¶
Lớp
unix_dialectxác định các thuộc tính thông thường của tệp CSV được tạo trên hệ thống UNIX, tức là sử dụng'\n'làm dấu kết thúc dòng và trích dẫn tất cả các trường. Nó được đăng ký với tên phương ngữ'unix'.Added in version 3.2.
- class csv.Sniffer¶
Lớp
Snifferđược sử dụng để suy ra định dạng của tệp CSV.Lớp
Sniffercung cấp hai phương thức:- sniff(sample, delimiters=None)¶
Phân tích sample đã cho và trả về lớp con
Dialectphản ánh các tham số được tìm thấy. Nếu tham số delimiters tùy chọn được đưa ra, nó được hiểu là một chuỗi chứa các ký tự phân cách hợp lệ có thể có.
- has_header(sample)¶
Phân tích văn bản mẫu (được cho là ở định dạng CSV) và trả về
Truenếu hàng đầu tiên xuất hiện là một chuỗi tiêu đề cột. Kiểm tra từng cột, một trong hai tiêu chí chính sẽ được xem xét để ước tính xem mẫu có chứa tiêu đề hay không:hàng thứ hai đến thứ n chứa các giá trị số
hàng thứ hai đến thứ n chứa các chuỗi trong đó độ dài của ít nhất một giá trị khác với độ dài của tiêu đề giả định của cột đó.
21 hàng sau tiêu đề được lấy mẫu; nếu hơn một nửa số cột + hàng đáp ứng tiêu chí,
Truesẽ được trả về.
Ghi chú
Phương pháp này là một phương pháp phỏng đoán thô và có thể tạo ra cả kết quả dương tính giả và âm tính giả.
Một ví dụ cho Sniffer sử dụng
với open('example.csv', newline='') là csvfile:
phương ngữ = csv.Sniffer().sniff(csvfile.read(1024))
csvfile.seek(0)
reader = csv.reader(csvfile, phương ngữ)
# ... xử lý nội dung file CSV tại đây ...
Mô-đun csv xác định các hằng số sau:
- csv.QUOTE_MINIMAL¶
Hướng dẫn các đối tượng
writerchỉ trích dẫn những trường chứa các ký tự đặc biệt như delimiter, quotechar,'\r','\n'hoặc bất kỳ ký tự nào trong lineterminator.
- csv.QUOTE_NONNUMERIC¶
Hướng dẫn các đối tượng
writertrích dẫn tất cả các trường không phải là số.Hướng dẫn các đối tượng
readerchuyển đổi tất cả các trường không có dấu ngoặc kép sang loạifloat.Ghi chú
Một số loại số, chẳng hạn như
bool,FractionhoặcIntEnum, có biểu diễn chuỗi không thể chuyển đổi thànhfloat. Chúng không thể được đọc ở chế độQUOTE_NONNUMERICvàQUOTE_STRINGS.
- csv.QUOTE_NONE¶
Hướng dẫn các đối tượng
writerkhông bao giờ trích dẫn các trường. Khi delimiter, quotechar, escapechar,'\r','\n'hiện tại hoặc bất kỳ ký tự nào trong lineterminator xuất hiện trong dữ liệu đầu ra, nó sẽ đứng trước ký tự escapechar hiện tại. Nếu escapechar không được đặt, người viết sẽ tăngErrornếu gặp bất kỳ ký tự nào yêu cầu thoát. Đặt quotechar thànhNoneđể ngăn nó thoát.Hướng dẫn các đối tượng
readerkhông thực hiện xử lý đặc biệt các ký tự trích dẫn.
- csv.QUOTE_NOTNULL¶
Hướng dẫn các đối tượng
writertrích dẫn tất cả các trường không phải làNone. Điều này tương tự nhưQUOTE_ALL, ngoại trừ việc nếu giá trị trường làNonethì một chuỗi trống (không trích dẫn) sẽ được ghi.Hướng dẫn các đối tượng
readerdiễn giải một trường trống (không có trích dẫn) làNonevà hoạt động nhưQUOTE_ALL.Added in version 3.12.
- csv.QUOTE_STRINGS¶
Hướng dẫn các đối tượng
writerluôn đặt dấu ngoặc kép xung quanh các trường là chuỗi. Điều này tương tự nhưQUOTE_NONNUMERIC, ngoại trừ việc nếu giá trị trường làNonethì một chuỗi trống (không trích dẫn) sẽ được ghi.Hướng dẫn các đối tượng
readerdiễn giải một chuỗi trống (không có trích dẫn) làNonevà hoạt động nhưQUOTE_NONNUMERIC.Added in version 3.12.
Mô-đun csv xác định ngoại lệ sau:
- exception csv.Error¶
Được tăng lên bởi bất kỳ chức năng nào khi phát hiện ra lỗi.
Các tham số phương ngữ và định dạng¶
Để dễ dàng chỉ định định dạng của bản ghi đầu vào và đầu ra, các tham số định dạng cụ thể được nhóm lại với nhau thành các phương ngữ. Một phương ngữ là một lớp con của lớp Dialect chứa nhiều thuộc tính khác nhau mô tả định dạng của tệp CSV. Khi tạo các đối tượng reader hoặc writer, lập trình viên có thể chỉ định một chuỗi hoặc một lớp con của lớp Dialect làm tham số phương ngữ. Ngoài hoặc thay vì tham số dialect, lập trình viên cũng có thể chỉ định các tham số định dạng riêng lẻ có cùng tên với các thuộc tính được xác định bên dưới cho lớp Dialect.
Các phương ngữ hỗ trợ các thuộc tính sau:
- Dialect.delimiter¶
Chuỗi một ký tự dùng để phân tách các trường. Nó mặc định là
','.
- Dialect.doublequote¶
Kiểm soát cách các phiên bản quotechar xuất hiện bên trong một trường sẽ được trích dẫn. Khi
True, ký tự được nhân đôi. KhiFalse, escapechar được sử dụng làm tiền tố cho quotechar. Nó mặc định làTrue.Ở đầu ra, nếu doublequote là
Falsevà không có escapechar nào được đặt,Errorsẽ được nâng lên nếu tìm thấy quotechar trong một trường.
- Dialect.escapechar¶
Chuỗi một ký tự được người viết sử dụng để thoát các ký tự cần thoát:
delimiter, quotechar,
'\r','\n'và bất kỳ ký tự nào trong lineterminator đều được thoát nếu quoting được đặt thànhQUOTE_NONE;quotechar bị thoát nếu doublequote là
False;chính escapechar.
Khi đọc, escapechar sẽ loại bỏ mọi ý nghĩa đặc biệt khỏi ký tự sau. Nó mặc định là
None, vô hiệu hóa việc thoát.Thay đổi trong phiên bản 3.11: Không được phép escapechar trống.
- Dialect.lineterminator¶
Chuỗi được sử dụng để kết thúc các dòng do
writertạo ra. Nó mặc định là'\r\n'.Ghi chú
readerđược mã hóa cứng để nhận ra'\r'hoặc'\n'là cuối dòng và bỏ qua lineterminator. Hành vi này có thể thay đổi trong tương lai.
- Dialect.quotechar¶
Chuỗi một ký tự được sử dụng để trích dẫn các trường chứa các ký tự đặc biệt, chẳng hạn như delimiter hoặc quotechar hoặc chứa các ký tự dòng mới (
'\r','\n'hoặc bất kỳ ký tự nào trong lineterminator). Nó mặc định là'"'. Có thể được đặt thànhNoneđể tránh thoát'"'nếu quoting được đặt thànhQUOTE_NONE.Thay đổi trong phiên bản 3.11: Không được phép quotechar trống.
- Dialect.quoting¶
Kiểm soát thời điểm người viết phải tạo dấu ngoặc kép và được người đọc nhận ra. Nó có thể nhận bất kỳ QUOTE_* constants nào và mặc định là
QUOTE_MINIMALnếu quotechar không phải làNonevàQUOTE_NONEnếu không.
Đối tượng đọc¶
Các đối tượng Reader (các phiên bản DictReader và các đối tượng được hàm reader() trả về) có các phương thức công khai sau:
- csvreader.__next__()¶
Trả về hàng tiếp theo của đối tượng có thể lặp của trình đọc dưới dạng danh sách (nếu đối tượng được trả về từ
reader()) hoặc một lệnh (nếu đó là phiên bảnDictReader), được phân tích cú pháp theoDialecthiện tại. Thông thường bạn nên gọi đây lànext(reader).
Đối tượng Reader có các thuộc tính công khai sau:
- csvreader.dialect¶
Mô tả chỉ đọc về phương ngữ được trình phân tích cú pháp sử dụng.
- csvreader.line_num¶
Số dòng được đọc từ trình vòng lặp nguồn. Giá trị này không giống với số lượng bản ghi được trả về vì các bản ghi có thể trải dài trên nhiều dòng.
Các đối tượng DictReader có thuộc tính public sau:
- DictReader.fieldnames¶
Nếu không được truyền dưới dạng tham số khi tạo đối tượng, thuộc tính này sẽ được khởi tạo khi truy cập lần đầu hoặc khi bản ghi đầu tiên được đọc từ tệp.
Đối tượng nhà văn¶
Các đối tượng writer (các phiên bản DictWriter và các đối tượng được hàm writer() trả về) có các phương thức công khai sau. Một row phải là một chuỗi hoặc số có thể lặp lại cho các đối tượng writer và một từ điển ánh xạ tên trường thành chuỗi hoặc số (bằng cách chuyển chúng qua str() trước) cho các đối tượng DictWriter. Lưu ý rằng số phức được viết ra bao quanh bởi dấu ngoặc đơn. Điều này có thể gây ra một số vấn đề cho các chương trình khác đọc tệp CSV (giả sử chúng hỗ trợ số phức).
- csvwriter.writerow(row, /)¶
Viết tham số row vào đối tượng file của người viết, được định dạng theo
Dialecthiện tại. Trả về giá trị trả về của lệnh gọi tới phương thức write của đối tượng tệp cơ bản.Thay đổi trong phiên bản 3.5: Đã thêm hỗ trợ cho các lần lặp tùy ý.
- csvwriter.writerows(rows, /)¶
Viết tất cả các phần tử trong rows (một đối tượng có thể lặp lại của row như được mô tả ở trên) vào đối tượng tệp của người viết, được định dạng theo phương ngữ hiện tại.
Đối tượng Writer có thuộc tính public sau:
- csvwriter.dialect¶
Mô tả chỉ đọc về phương ngữ được người viết sử dụng.
Các đối tượng DictWriter có phương thức công khai sau:
- DictWriter.writeheader()¶
Viết một hàng có tên trường (như được chỉ định trong hàm tạo) vào đối tượng tệp của người viết, được định dạng theo phương ngữ hiện tại. Trả về giá trị trả về của lệnh gọi
csvwriter.writerow()được sử dụng nội bộ.Added in version 3.2.
Thay đổi trong phiên bản 3.8:
writeheader()hiện cũng trả về giá trị được trả về bởi phương thứccsvwriter.writerow()mà nó sử dụng nội bộ.
Ví dụ¶
Ví dụ đơn giản nhất về đọc tệp CSV:
nhập csv
với open('some.csv', newline='') là f:
reader = csv.reader(f)
cho hàng trong trình đọc:
in (hàng)
Đọc tệp có định dạng thay thế:
nhập csv
với open('passwd', newline='') là f:
reader = csv.reader(f, delimiter=':', quote=csv.QUOTE_NONE)
cho hàng trong trình đọc:
in (hàng)
Ví dụ viết đơn giản nhất có thể tương ứng là:
nhập csv
với open('some.csv', 'w', newline='') là f:
nhà văn = csv.writer(f)
writer.writerows(someiterable)
Vì open() được sử dụng để mở tệp CSV để đọc nên theo mặc định, tệp sẽ được giải mã thành unicode bằng cách sử dụng mã hóa mặc định của hệ thống (xem locale.getencoding()). Để giải mã một tệp bằng cách mã hóa khác, hãy sử dụng đối số encoding của open:
nhập csv
với open('some.csv', newline='',coding='utf-8') là f:
reader = csv.reader(f)
cho hàng trong trình đọc:
in (hàng)
Điều tương tự cũng áp dụng cho việc ghi bằng thứ gì đó không phải là mã hóa mặc định của hệ thống: chỉ định đối số mã hóa khi mở tệp đầu ra.
Đăng ký một phương ngữ mới:
nhập csv
csv.register_dialect('unixpwd', delimiter=':', quote=csv.QUOTE_NONE)
với open('passwd', newline='') là f:
reader = csv.reader(f, 'unixpwd')
Cách sử dụng trình đọc nâng cao hơn một chút --- bắt và báo cáo lỗi:
nhập csv, sys
tên tệp = 'some.csv'
với open(filename, newline='') là f:
reader = csv.reader(f)
thử:
cho hàng trong trình đọc:
in (hàng)
ngoại trừ csv.Error là e:
sys.exit(f'file {filename}, dòng {reader.line_num}: {e}')
Và mặc dù mô-đun không hỗ trợ trực tiếp các chuỗi phân tích cú pháp, nhưng nó có thể được thực hiện dễ dàng
nhập csv
cho hàng trong csv.reader(['one,two, three']):
in (hàng)
Chú thích cuối trang