2009-08-14 31 views
8

Tôi đang cố gắng phân tích cú pháp tệp CSV bằng mô-đun csv của Python (cụ thể là lớp DictReader). Có cách nào của Pythonic để phát hiện các trường trống hoặc thiếu và ném một lỗi không?Làm cách nào để phát hiện các trường bị thiếu trong tệp CSV theo cách Pythonic?

Đây là một tập tin mẫu sử dụng các tiêu đề sau: TÊN, NHÃN, GIÁ TRỊ

foo,bar,baz 
yes,no 
x,y,z 

Khi phân tích cú pháp, tôi muốn dòng thứ hai để ném ra một lỗi kể từ khi nó còn thiếu lĩnh vực VALUE.

Dưới đây là một đoạn mã trong đó cho thấy làm thế nào tôi đang tiếp cận này (bỏ qua các chuỗi mã hóa cứng ... họ chỉ xuất hiện cho ngắn gọn):

import csv 

HEADERS = ["name", "label", "value" ] 
fileH = open('configFile') 
reader = csv.DictReader(fileH, HEADERS) 

for row in reader: 
    if row["name"] is None or row["name"] == "": 
     # raise Error 
    if row["label"] is None or row["label"] == "": 
     # raise Error 
    ... 
fileH.close() 

Có cách nào sạch của kiểm tra các trường trong tệp CSV w/out có một loạt các câu lệnh if? Nếu tôi cần thêm nhiều trường hơn, tôi cũng sẽ cần nhiều điều kiện hơn, điều mà tôi muốn tránh nếu có thể.

Trả lời

14
if any(row[key] in (None, "") for key in row): 
    # raise error 

Sửa: Thậm chí tốt hơn:

if any(val in (None, "") for val in row.itervalues()): 
    # raise error 
+0

Cách thức ngọt ngào của Pythonic! –

+0

Phương pháp này là khá nhiều không tương thích với hành vi của csv.DictReader. Nó sẽ lặp qua tất cả các phím trong hàng, mặc dù một số khóa có thể bị DictReader loại bỏ vì chúng không được đề cập rõ ràng trong HEADERS. Xem thêm tại đây: http://docs.python.org/library/csv.html#csv.DictReader – Triptych

+0

@Triptych: Có tối đa một khóa bổ sung như vậy (giá trị được chuyển làm khóa khôi phục cho hàm tạo). Tôi không thấy vấn đề với điều đó. – balpha

1

Một cái gì đó như thế này?

... 
for row in reader: 
    for column, value in row.items(): 
     if value is None or value == "": 
      # raise Error, using value of column to say which field is missing 

Bạn có thể sử dụng 'if not value:' làm bài kiểm tra thay vì kiểm tra rõ ràng hơn bạn đã đưa ra.

2

Kể từ None và chuỗi rỗng cả đánh giá để False, bạn nên xem xét việc này:

for row in reader: 
    for header in HEADERS: 
     if not row[header]: 
      # raise error 

Lưu ý rằng, không giống như một số câu trả lời khác , bạn sẽ vẫn có tùy chọn nâng cao lỗi thông tin, tiêu đề cụ thể.

+0

Điều này sẽ dẫn đến các kết quả sai nếu bạn có giá trị số 0 trong bất kỳ cột nào và 'quoting' được đặt thành' csv.QUOTE_NONNUMERIC'. –

1

Mã này sẽ cung cấp, cho mỗi hàng, một danh sách các tên trường không có mặt (hoặc trống) cho hàng đó. Sau đó, bạn có thể cung cấp một ngoại lệ chi tiết hơn, chẳng hạn như "Thiếu trường: foo, baz".

def missing(row): 
    return [h for h in HEADERS if not row.get(h)] 

for row in reader: 
    m = missing(row) 
    if missing: 
     # raise exception with list of missing field names 
0

Nếu bạn sử dụng matplotlib.mlab.csv2rec, nó đã lưu nội dung của tệp vào một mảng và nêu lỗi nếu một trong các giá trị bị thiếu.

>>> from matplotlib.mlab import csv2rec 
>>> content_array = csv2rec('file.txt') 
IndexError: list index out of range 

Vấn đề là không có cách đơn giản để tùy chỉnh hành vi này hoặc cung cấp giá trị mặc định trong trường hợp thiếu hàng. Hơn nữa, các thông báo lỗi không phải là rất giải thích (có thể hữu ích để gửi một báo cáo lỗi ở đây).

p.s. kể từ khi csv2rec lưu nội dung của tệp vào một bản ghi khó khăn, sẽ dễ dàng hơn để lấy các giá trị bằng Không.

Các vấn đề liên quan