파이썬에서 파일을 읽고 쓰는 유니 코드 (UTF-8) 것을 이해하는 데 약간의 두뇌

텍스트를 읽고 파일로 쓰는 것을 이해하는 데 약간의 두뇌 장애가 있습니다 (Python 2.4).

# The string, which has an a-acute in it.
ss = u'Capit\xe1n'
ss8 = ss.encode('utf8')
repr(ss), repr(ss8)

( “u’Capit \ xe1n ‘”, “‘Capit \ xc3 \ xa1n ‘”)

print ss, ss8
print >> open('f1','w'), ss8

>>> file('f1').read()
'Capit\xc3\xa1n\n'

그래서 내가 Capit\xc3\xa1n좋아하는 편집기 인 파일 f2에 입력합니다.

그때:

>>> open('f1').read()
'Capit\xc3\xa1n\n'
>>> open('f2').read()
'Capit\\xc3\\xa1n\n'
>>> open('f1').read().decode('utf8')
u'Capit\xe1n\n'
>>> open('f2').read().decode('utf8')
u'Capit\\xc3\\xa1n\n'

내가 여기서 이해하지 못하는 것은 무엇입니까? 분명히 내가 놓친 몇 가지 중요한 마법 (또는 좋은 감각)이 있습니다. 적절한 변환을 위해 텍스트 파일에 한 가지 유형이 있습니까?

내가 정말로 여기에서 실패한 것은 UTF-8 표현의 요점은 실제로 외부에서 올 때 파이썬이 그것을 인식하도록 할 수 없다면입니다. 어쩌면 JSON은 문자열을 덤프하고 대신 사용할 수 있습니다. 요컨대, 파일에서 올 때 파이썬이 인식하고 디코딩 할이 유니 코드 객체의 ASCII 표현이 있습니까? 그렇다면 어떻게 얻습니까?

>>> print simplejson.dumps(ss)
'"Capit\u00e1n"'
>>> print >> file('f3','w'), simplejson.dumps(ss)
>>> simplejson.load(open('f3'))
u'Capit\xe1n'


답변

표기법에서

u'Capit\xe1n\n'

“\ xe1″은 1 바이트 만 나타냅니다. “\ x”는 “e1″이 16 진수임을 나타냅니다. 당신이 쓸 때

Capit\xc3\xa1n

파일에 “\ xc3″이 있습니다. 그것들은 4 바이트이며 코드에서 모두 읽습니다. 당신이 그들을 표시 할 때 이것을 볼 수 있습니다 :

>>> open('f2').read()
'Capit\\xc3\\xa1n\n'

백 슬래시가 백 슬래시를 이스케이프 한 것을 볼 수 있습니다. 따라서 문자열에는 “\”, “x”, “c”및 “3”의 4 바이트가 있습니다.

편집하다:

다른 사람들이 답변에서 지적했듯이 편집기에 문자를 입력하면 편집기가 UTF-8 로의 변환을 처리하고 저장해야합니다.

실제로이 형식의 문자열이있는 경우 string_escape코덱을 사용하여 일반 문자열로 디코딩 할 수 있습니다 .

In [15]: print 'Capit\\xc3\\xa1n\n'.decode('string_escape')
Capitán

결과는 악센트 문자가 \\xc3\\xa1원래 문자열 로 작성된 2 바이트로 표시되는 UTF-8로 인코딩 된 문자열입니다. 유니 코드 문자열을 원한다면 UTF-8로 다시 디코딩해야합니다.

편집 : 파일에 UTF-8이 없습니다. 실제로 어떻게 보일지 보려면 :

s = u'Capit\xe1n\n'
sutf8 = s.encode('UTF-8')
open('utf-8.out', 'w').write(sutf8)

파일 utf-8.out내용을 편집기로 저장 한 파일 내용과 비교하십시오 .


답변

인코딩 및 디코딩 방법을 망칠 필요없이 파일을 열 때 인코딩을 지정하는 것이 더 쉽다는 것을 알았습니다. 이 io모듈 (Python 2.6에 추가)은 io.open인코딩 매개 변수가있는 함수를 제공합니다 .

io모듈 에서 open 메소드를 사용하십시오 .

>>>import io
>>>f = io.open("test", mode="r", encoding="utf-8")

그런 다음 f의 read () 함수를 호출하면 인코딩 된 유니 코드 객체가 반환됩니다.

>>>f.read()
u'Capit\xe1l\n\n'

Python 3에서 io.open함수는 내장 함수의 별명입니다 open. 내장 된 open 함수는 Python 2가 아닌 Python 3의 인코딩 인수 만 지원합니다.

편집 : 이전에는이 ​​답변에서 코덱 모듈을 권장했습니다 . 코덱 모듈은 혼합 할 때 문제가 발생할 수 read()readline() 이 대답은 지금은 권장하므로, IO 대신 모듈을.

코덱 모듈에서 open 메소드를 사용하십시오.

>>>import codecs
>>>f = codecs.open("test", "r", "utf-8")

그런 다음 f의 read () 함수를 호출하면 인코딩 된 유니 코드 객체가 반환됩니다.

>>>f.read()
u'Capit\xe1l\n\n'

파일 인코딩을 알고 있다면 코덱 패키지를 사용하는 것이 훨씬 덜 혼란 스러울 것입니다.

http://docs.python.org/library/codecs.html#codecs.open을 참조 하십시오.


답변

이제 Python3에 필요한 것은 open(Filename, 'r', encoding='utf-8')

[요청 된 설명을 위해 2016-02-10에 편집]

Python3은 인코딩 매개 변수를 열린 함수에 추가했습니다 . 열기 기능에 대한 다음 정보는 여기에서 수집됩니다. https://docs.python.org/3/library/functions.html#open

open(file, mode='r', buffering=-1,
      encoding=None, errors=None, newline=None,
      closefd=True, opener=None)

인코딩은 파일을 디코딩하거나 인코딩하는 데 사용되는 인코딩의 이름입니다. 텍스트 모드에서만 사용해야합니다. 기본 인코딩은 플랫폼에 따라 다르지만 ( locale.getpreferredencoding ()이
반환하는 방식) Python에서 지원하는 모든 텍스트 인코딩을 사용할 수 있습니다. 지원되는 인코딩 목록은 코덱 모듈을 참조하십시오 .

따라서 encoding='utf-8'open 함수에 매개 변수로 추가 하면 파일 읽기 및 쓰기가 모두 utf8 (이제 Python에서 수행되는 모든 작업의 ​​기본 인코딩 임)로 수행됩니다.


답변

그래서, 내가 찾고있는 솔루션을 찾았습니다.

print open('f2').read().decode('string-escape').decode("utf-8")

여기에 유용한 몇 가지 특이한 코덱이 있습니다. 이 특정 읽기를 통해 Python 내에서 UTF-8 표현을 가져 와서 ASCII 파일로 복사하여 유니 코드로 읽을 수 있습니다. “문자열 이스케이프”디코드에서는 슬래시가 두 배가되지 않습니다.

이것은 내가 상상했던 일종의 왕복 여행을 허용합니다.


답변

# -*- encoding: utf-8 -*-

# converting a unknown formatting file in utf-8

import codecs
import commands

file_location = "jumper.sub"
file_encoding = commands.getoutput('file -b --mime-encoding %s' % file_location)

file_stream = codecs.open(file_location, 'r', file_encoding)
file_output = codecs.open(file_location+"b", 'w', 'utf-8')

for l in file_stream:
    file_output.write(l)

file_stream.close()
file_output.close()

답변

실제로 이것은 Python 3.2에서 UTF-8 인코딩으로 파일을 읽는 데 도움이되었습니다.

import codecs
f = codecs.open('file_name.txt', 'r', 'UTF-8')
for line in f:
    print(line)

답변

유니 코드 문자열을 읽은 다음 HTML로 보내려면 다음과 같이하십시오.

fileline.decode("utf-8").encode('ascii', 'xmlcharrefreplace')

파이썬 기반 http 서버에 유용합니다.