Python 2.7로 유니 코드를 포함한 CSV 파일 읽기 및 쓰기
저는 Python을 처음 사용하는데 Python을 사용하여 CSV 파일을 읽고 쓰는 방법에 대한 질문이 있습니다. 내 파일에는 독일, 프랑스어 등이 포함되어 있습니다. 내 코드에 따르면 파일은 Python에서 올바르게 읽을 수 있지만 새 CSV 파일에 쓰면 유니 코드가 이상한 문자가됩니다.
데이터는 다음과 같습니다.
그리고 내 코드는 다음과 같습니다.
import csv
f=open('xxx.csv','rb')
reader=csv.reader(f)
wt=open('lll.csv','wb')
writer=csv.writer(wt,quoting=csv.QUOTE_ALL)
wt.close()
f.close()
결과는 다음과 같습니다.
문제를 해결하기 위해 무엇을해야하는지 알려주시겠습니까? 대단히 감사합니다!
또 다른 대안 :
unicodecsv 패키지의 코드 사용 ...
https://pypi.python.org/pypi/unicodecsv/
>>> import unicodecsv as csv
>>> from io import BytesIO
>>> f = BytesIO()
>>> w = csv.writer(f, encoding='utf-8')
>>> _ = w.writerow((u'é', u'ñ'))
>>> _ = f.seek(0)
>>> r = csv.reader(f, encoding='utf-8')
>>> next(r) == [u'é', u'ñ']
True
이 모듈은 STDLIB csv 모듈과 호환되는 API입니다.
적절하게 인코딩 및 디코딩하십시오.
이 예제는 utf-8의 일부 예제 텍스트를 csv 파일로 라운드 트립하고 다시 표시하여 다음을 보여줍니다.
# -*- coding: utf-8 -*-
import csv
tests={'German': [u'Straße',u'auslösen',u'zerstören'],
'French': [u'français',u'américaine',u'épais'],
'Chinese': [u'中國的',u'英語',u'美國人']}
with open('/tmp/utf.csv','w') as fout:
writer=csv.writer(fout)
writer.writerows([tests.keys()])
for row in zip(*tests.values()):
row=[s.encode('utf-8') for s in row]
writer.writerows([row])
with open('/tmp/utf.csv','r') as fin:
reader=csv.reader(fin)
for row in reader:
temp=list(row)
fmt=u'{:<15}'*len(temp)
print fmt.format(*[s.decode('utf-8') for s in temp])
인쇄물:
German Chinese French
Straße 中國的 français
auslösen 英語 américaine
zerstören 美國人 épais
유니 코드를 다루는 방법을 보여주는 csv 모듈 문서 의 끝에 예제가 있습니다 . 아래는 해당 예제 에서 직접 복사 한 것입니다 . 읽거나 쓴 문자열은 유니 코드 문자열입니다. UnicodeWriter.writerows
예를 들어에 바이트 문자열을 전달하지 마십시오 .
import csv,codecs,cStringIO
class UTF8Recoder:
def __init__(self, f, encoding):
self.reader = codecs.getreader(encoding)(f)
def __iter__(self):
return self
def next(self):
return self.reader.next().encode("utf-8")
class UnicodeReader:
def __init__(self, f, dialect=csv.excel, encoding="utf-8-sig", **kwds):
f = UTF8Recoder(f, encoding)
self.reader = csv.reader(f, dialect=dialect, **kwds)
def next(self):
'''next() -> unicode
This function reads and returns the next line as a Unicode string.
'''
row = self.reader.next()
return [unicode(s, "utf-8") for s in row]
def __iter__(self):
return self
class UnicodeWriter:
def __init__(self, f, dialect=csv.excel, encoding="utf-8-sig", **kwds):
self.queue = cStringIO.StringIO()
self.writer = csv.writer(self.queue, dialect=dialect, **kwds)
self.stream = f
self.encoder = codecs.getincrementalencoder(encoding)()
def writerow(self, row):
'''writerow(unicode) -> None
This function takes a Unicode string and encodes it to the output.
'''
self.writer.writerow([s.encode("utf-8") for s in row])
data = self.queue.getvalue()
data = data.decode("utf-8")
data = self.encoder.encode(data)
self.stream.write(data)
self.queue.truncate(0)
def writerows(self, rows):
for row in rows:
self.writerow(row)
with open('xxx.csv','rb') as fin, open('lll.csv','wb') as fout:
reader = UnicodeReader(fin)
writer = UnicodeWriter(fout,quoting=csv.QUOTE_ALL)
for line in reader:
writer.writerow(line)
입력 (UTF-8 인코딩) :
American,美国人
French,法国人
German,德国人
산출:
"American","美国人"
"French","法国人"
"German","德国人"
str
python2에서 bytes
실제로 있기 때문 입니다 . 따라서 unicode
csv 에 쓰 려면 인코딩 unicode
을 str
사용하여 utf-8
인코딩 해야합니다 .
def py2_unicode_to_str(u):
# unicode is only exist in python2
assert isinstance(u, unicode)
return u.encode('utf-8')
사용 class csv.DictWriter(csvfile, fieldnames, restval='', extrasaction='raise', dialect='excel', *args, **kwds)
:
- py2
csvfile
:open(fp, 'w')
bytes
인코딩 된 키와 값을 전달합니다.utf-8
writer.writerow({py2_unicode_to_str(k): py2_unicode_to_str(v) for k,v in row.items()})
- py3
csvfile
:open(fp, 'w')
- 전달 정상 딕셔너리는 포함
str
으로서row
행writer.writerow(row)
마지막으로 코드
import sys
is_py2 = sys.version_info[0] == 2
def py2_unicode_to_str(u):
# unicode is only exist in python2
assert isinstance(u, unicode)
return u.encode('utf-8')
with open('file.csv', 'w') as f:
if is_py2:
data = {u'Python中国': u'Python中国', u'Python中国2': u'Python中国2'}
# just one more line to handle this
data = {py2_unicode_to_str(k): py2_unicode_to_str(v) for k, v in data.items()}
fields = list(data[0])
writer = csv.DictWriter(f, fieldnames=fields)
for row in data:
writer.writerow(row)
else:
data = {'Python中国': 'Python中国', 'Python中国2': 'Python中国2'}
fields = list(data[0])
writer = csv.DictWriter(f, fieldnames=fields)
for row in data:
writer.writerow(row)
결론
python3에서는 unicode str
.
In python2, use unicode
handle text, use str
when I/O occurs.
I had the very same issue. The answer is that you are doing it right already. It is the problem of MS Excel. Try opening the file with another editor and you will notice that your encoding was successful already. To make MS Excel happy, move from UTF-8 to UTF-16. This should work:
class UnicodeWriter:
def __init__(self, f, dialect=csv.excel_tab, encoding="utf-16", **kwds):
# Redirect output to a queue
self.queue = StringIO.StringIO()
self.writer = csv.writer(self.queue, dialect=dialect, **kwds)
self.stream = f
# Force BOM
if encoding=="utf-16":
import codecs
f.write(codecs.BOM_UTF16)
self.encoding = encoding
def writerow(self, row):
# Modified from original: now using unicode(s) to deal with e.g. ints
self.writer.writerow([unicode(s).encode("utf-8") for s in row])
# Fetch UTF-8 output from the queue ...
data = self.queue.getvalue()
data = data.decode("utf-8")
# ... and reencode it into the target encoding
data = data.encode(self.encoding)
# strip BOM
if self.encoding == "utf-16":
data = data[2:]
# write to the target stream
self.stream.write(data)
# empty queue
self.queue.truncate(0)
def writerows(self, rows):
for row in rows:
self.writerow(row)
I couldn't respond to Mark above, but I just made one modification which fixed the error which was caused if data in the cells was not unicode, i.e. float or int data. I replaced this line into the UnicodeWriter function: "self.writer.writerow([s.encode("utf-8") if type(s)==types.UnicodeType else s for s in row])" so that it became:
class UnicodeWriter:
def __init__(self, f, dialect=csv.excel, encoding="utf-8-sig", **kwds):
self.queue = cStringIO.StringIO()
self.writer = csv.writer(self.queue, dialect=dialect, **kwds)
self.stream = f
self.encoder = codecs.getincrementalencoder(encoding)()
def writerow(self, row):
'''writerow(unicode) -> None
This function takes a Unicode string and encodes it to the output.
'''
self.writer.writerow([s.encode("utf-8") if type(s)==types.UnicodeType else s for s in row])
data = self.queue.getvalue()
data = data.decode("utf-8")
data = self.encoder.encode(data)
self.stream.write(data)
self.queue.truncate(0)
def writerows(self, rows):
for row in rows:
self.writerow(row)
You will also need to "import types".
'IT TIP' 카테고리의 다른 글
오류-현재 연결과 관련된 트랜잭션이 완료되었지만 삭제되지 않았습니다. (0) | 2020.11.26 |
---|---|
수평 스크롤바 및 수직 스크롤바가 켜져있는 고정 헤더 테이블 (0) | 2020.11.26 |
각 키 값에 대해 가장 최근의 타임 스탬프가있는 행을 어떻게 선택할 수 있습니까? (0) | 2020.11.26 |
ImageMagick을 사용하여 EXIF 방향 감지 및 이미지 회전 (0) | 2020.11.26 |
Pandas DataFrame을 목록 목록으로 변환 (0) | 2020.11.26 |