Cách ghi UTF-8 trong tệp CSV


83

Tôi đang cố gắng tạo tệp văn bản ở định dạng csv từ PyQt4 QTableWidget. Tôi muốn viết văn bản bằng mã hóa UTF-8 vì nó chứa các ký tự đặc biệt. Tôi sử dụng mã sau:

import codecs
...
myfile = codecs.open(filename, 'w','utf-8')
...
f = result.table.item(i,c).text()
myfile.write(f+";")

Nó hoạt động cho đến khi ô chứa một ký tự đặc biệt. Tôi cũng đã thử với

myfile = open(filename, 'w')
...
f = unicode(result.table.item(i,c).text(), "utf-8")

Nhưng nó cũng dừng lại khi một ký tự đặc biệt xuất hiện. Tôi không biết mình đang làm gì sai.


"nó đứng đầu"? Điều đó nghĩa là gì? lỗi gì bạn nhận được? Đầu vào của bạn là gì?

Đầu vào là một pyqt4 QTableWidgetItem. Vấn đề là tôi không gặp bất kỳ lỗi nào vì tập lệnh đang chạy dưới dạng plugin.
Martin

Sau đó cố gắng tái tạo vấn đề bên ngoài QT.

Đã tìm ra giải pháp. Tôi phải viếtmyfile.write(u"%s"&f+";")
Martin

Câu trả lời:


106

Từ shell của bạn chạy:

pip2 install unicodecsv

Và (không giống như câu hỏi ban đầu), giả sử bạn đang sử dụng csvmô-đun tích hợp sẵn của Python , hãy chuyển
import csvthành
import unicodecsv as csvmã của bạn.


29
Nó không hoạt động chỉ bằng cách thay thế nhập, tôi cũng phải thêm mã hóa khi tạo trình viết: writer = csv.writer(out, dialect='excel', encoding='utf-8')và tạo trình xử lý tệp bằng open(..., không codecs.open(... .
Suzana

4
Tôi đã thử tất cả các đề xuất trên StackOverflow và chỉ cái này phù hợp với tôi.
Charles Chow

90

Nó rất đơn giản cho Python 3.x ( docs ).

import csv

with open('output_file_name', 'w', newline='', encoding='utf-8') as csv_file:
    writer = csv.writer(csv_file, delimiter=';')
    writer.writerow('my_utf8_string')

Đối với Python 2.x, hãy xem tại đây .


1
nếu nội dung của writerownó không phải là utf-8 thì sao? nó sẽ hoạt động?
CKM

1
Tuyệt vời không cần cài đặt pip của bên thứ ba.
Vaibhav Vishal


3

Đối với tôi, UnicodeWriterlớp từ tài liệu mô-đun CSV của Python 2 không thực sự hoạt động vì nó phá vỡ csv.writer.write_row()giao diện.

Ví dụ:

csv_writer = csv.writer(csv_file)
row = ['The meaning', 42]
csv_writer.writerow(row)

hoạt động, trong khi:

csv_writer = UnicodeWriter(csv_file)
row = ['The meaning', 42]
csv_writer.writerow(row)

sẽ ném AttributeError: 'int' object has no attribute 'encode'.

Như UnicodeWriterrõ ràng là hy vọng tất cả các giá trị cột là chuỗi, chúng ta có thể chuyển đổi các giá trị bản thân và chỉ cần sử dụng các mô-đun CSV mặc định:

def to_utf8(lst):
    return [unicode(elem).encode('utf-8') for elem in lst]

...
csv_writer.writerow(to_utf8(row))

Hoặc chúng tôi thậm chí có thể khỉ vá csv_writer để thêm một write_utf8_rowchức năng - bài tập được để cho người đọc.


2

Các ví dụ trong tài liệu Python cho thấy cách viết tệp Unicode CSV: http://docs.python.org/2/library/csv.html#examples

(không thể sao chép mã ở đây vì nó được bảo vệ bởi bản quyền)


1
Cảm ơn các liên kết. Nó rất hữu ích. Theo hiểu biết của tôi, ngay cả khi bạn đã đăng liên kết, bạn không thể sao chép, dán mã vào đây? (+1 vì nợ bản quyền)
Mutant

1
@Mutant: Code không giống như các bài báo khoa học. Mã được bảo vệ bởi bản quyền. Mặc dù tôi chắc chắn 99,999% rằng chủ sở hữu Python sẽ không kiện SO vì sao chép mã của họ, nhưng tôi không muốn đọc giấy phép dài dòng của họ để tìm hiểu xem nó có được phép hay không. Ngoài ra, nó tốt để nhắc nhở mọi người một lần trong một thời gian mà "Tôi có thể nhìn thấy nó trên màn hình của tôi" = "Tôi có thể làm bất cứ điều gì tôi muốn với nó" :-)!
Aaron Digulla

1
Cảm ơn vì đã nhắc nhở. Thật không may, thế giới chúng ta đang sống trở nên quá nhanh (một cách vô lý) và bất cẩn khi thông tin đang chảy nhanh hơn người ta có thể tưởng tượng, nó yêu cầu nhắc nhở một lần và ngay cả khi có hạn chế quan trọng. Cảm ơn vì điều đó :)
Mutant

2
Liên kết tài liệu là bán hữu ích (ví dụ tốt hơn), nhưng đối số "bản quyền" ở đây bị thổi phồng quá mức và asinine. Python là nguồn mở rõ ràng ( v2 v3 ). Giấy phép rõ ràng: "miễn phí bản quyền, giấy phép trên toàn thế giới để tái sản xuất, phân tích, kiểm tra, biểu diễn và / hoặc hiển thị công khai, chuẩn bị các tác phẩm phái sinh, phân phối ... [v.v., v.v.]" Ngay cả cụm từ đơn giản tại đầu trang, "tương thích với GPL" sẽ mang lại cho bạn sự thoải mái. Chia sẻ nội dung nguồn mở. Thậm chí sửa đổi nó nếu bạn muốn. Đó là mã nguồn mở vì một lý do.
alttag

@alttag Sao chép hoặc sử dụng mã GPLd trong một dự án có nghĩa là tất cả các mã khác trong cùng một dự án hiện cũng thuộc GPL. Vì tôi không phải là luật sư bản quyền nên tôi không biết điều đó có nghĩa là gì đối với mã được xuất bản trên một trang web.
Aaron Digulla

0

Đối với python2, bạn có thể sử dụng mã này trước csv_writer.writerows(rows)
Mã này sẽ KHÔNG chuyển đổi số nguyên thành chuỗi utf-8

def encode_rows_to_utf8 (hàng):
    encoded_rows = []
    cho hàng trong hàng:
        encoded_row = []
        cho giá trị trong hàng:
            if isinstance (value, basestring):
                value = unicode (value) .encode ("utf-8")
            encoded_row.append (giá trị)
        encoded_rows.append (encoded_row)
    trả về mã hóa_rows

-1

Một cách hack rất đơn giản là sử dụng json import thay vì csv. Ví dụ: thay vì csv.writer chỉ cần làm như sau:

    fd = codecs.open(tempfilename, 'wb', 'utf-8')  
    for c in whatever :
        fd.write( json.dumps(c) [1:-1] )   # json dumps writes ["a",..]
        fd.write('\n')
    fd.close()

Về cơ bản, với danh sách các trường theo đúng thứ tự, chuỗi được định dạng json giống với một dòng csv ngoại trừ [và] ở đầu và cuối tương ứng. Và json dường như mạnh mẽ đến utf-8 trong python 2. *

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.