텍스트 파일에 유니 코드 텍스트를 작성 하시겠습니까?


225

Google 문서에서 데이터를 가져 와서 처리하고 파일에 씁니다 (결국 Wordpress 페이지에 붙여 넣습니다).

비 ASCII 기호가 있습니다. HTML 소스에서 사용할 수있는 심볼로 안전하게 변환하려면 어떻게해야합니까?

현재 나는 모든 것을 유니 코드로 변환하고 파이썬 문자열로 모두 결합 한 다음 다음을 수행합니다.

import codecs
f = codecs.open('out.txt', mode="w", encoding="iso-8859-1")
f.write(all_html.encode("iso-8859-1", "replace"))

마지막 줄에 인코딩 오류가 있습니다.

UnicodeDecodeError : 'ascii'코덱이 12286 위치에서 바이트 0xa0을 디코딩 할 수 없습니다 : 서 수가 범위 내에 있지 않습니다 (128)

부분 솔루션 :

이 파이썬은 오류없이 실행됩니다.

row = [unicode(x.strip()) if x is not None else u'' for x in row]
all_html = row[0] + "<br/>" + row[1]
f = open('out.txt', 'w')
f.write(all_html.encode("utf-8"))

그러나 실제 텍스트 파일을 열면 다음과 같은 많은 기호가 나타납니다.

Qur’an 

텍스트 파일이 아닌 다른 파일에 쓸 필요가 있습니까?


1
프로그램을 여는 데 사용중인 프로그램이 UTF-8 텍스트를 올바르게 해석하지 않습니다. 파일을 UTF-8로 여는 옵션이 있어야합니다.
Thomas K

답변:


322

객체를 처음 가져올 때 유니 코드 객체로 디코딩하고 필요에 따라 인코딩하는 방식으로 유니 코드 객체를 최대한 독점적으로 처리하십시오.

문자열이 실제로 유니 코드 객체 인 경우 파일에 쓰기 전에 유니 코드로 인코딩 된 문자열 객체로 변환해야합니다.

foo = u'Δ, Й, ק, ‎ م, ๗, あ, 叶, 葉, and 말.'
f = open('test', 'w')
f.write(foo.encode('utf8'))
f.close()

해당 파일을 다시 읽으면 유니 코드 객체로 디코딩 할 수있는 유니 코드로 인코딩 된 문자열이 나타납니다.

f = file('test', 'r')
print f.read().decode('utf8')

감사. 이것은 오류없이 실행되지만 텍스트 파일을 열면 이상한 기호가 많이 보입니다. :) 텍스트를 복사하여 Wordpress 페이지에 붙여 넣어야합니다 (묻지 마십시오). 실제로 존재하는 기호를 인쇄 할 수있는 방법이 있습니까? 나는 txt 파일이 아니라 다른 것으로 추측합니까?
사이먼

1
텍스트 파일을 여는 데 무엇을 사용하고 있습니까? 나는 당신이 Windows를 사용하고 있다고 추측하고 메모장에서 열 수 있습니다.이 인코딩은 너무 지능적이지 않습니다. 워드 패드에서 열면 어떻게됩니까?
quasistoic

@quasistoic 파일 방법은 어디에서 형성됩니까?
Omar Cusma Fait

stackoverflow.com/a/5513856/6580199에 설명 된대로 이진 모드를 켜야했습니다. 즉 f = open ( 'test', 'wb') -그렇지 않으면 "TypeError : write () 인수가 str이어야합니다. not bytes "
Benji

72

Python 2.6 이상에서는 Python 3에서 기본값 ( builtin )을 사용할io.open()있습니다 .open()

import io

with io.open(filename, 'w', encoding=character_encoding) as file:
    file.write(unicode_text)

점진적으로 텍스트를 작성해야하는 경우 ( unicode_text.encode(character_encoding)여러 번 호출 할 필요가 없음) 더 편리 할 수 ​​있습니다 . codecs모듈 과 달리 , io모듈은 적절한 범용 줄 바꾸기를 지원합니다.


1
남자, 나는 이것을 찾기 위해 많은 시간을 보냈다! 감사합니다!
게오르기 고보 조프

2
이것은 Python 3에서도 작동합니다 (명백하지만 여전히 지적 할 가치가 있습니다).
Hippo

37

유니 코드 문자열 처리는 이미 Python 3에서 표준화되었습니다.

  1. 문자는 메모리의 유니 코드 (32 비트)에 이미 저장되어 있습니다.
  2. utf-8로만 파일을 열면됩니다
    (32 비트 유니 코드에서 가변 바이트 길이의 utf-8 로의 변환은 메모리에서 파일로 자동 수행됩니다).

    out1 = "(嘉南大圳 ㄐㄧㄚ ㄋㄢˊ ㄉㄚˋ ㄗㄨㄣˋ )"
    fobj = open("t1.txt", "w", encoding="utf-8")
    fobj.write(out1)
    fobj.close()

그러나 이것은 Python 2에서 작동하지 않습니다. (이 파이썬 3 코드에서는 너무 간결하고 합리적으로 보입니다)
Liwen Zhao

파이썬 2에서는 작동하지 않습니다. 우리는 파이썬 3에 머물러 있습니다. 3이 훨씬 좋습니다.
david m lee

18

열린 codecs.open파일은 unicode데이터 를 가져 와서 인코딩 한 iso-8859-1후 파일에 쓰는 파일입니다. 그러나, 당신이 쓰려고하는 것은 아니다 unicode; 당신은 unicode그것을 iso-8859-1 자신의 것으로 받아들이고 인코딩합니다 . 이것이 unicode.encode메소드가하는 일이며, 유니 코드 문자열을 인코딩 한 결과는 바이트 스트링 ( str유형)입니다.

당신도 정상 사용해야 open()하고, 유니 코드를 직접, 또는 (일반적으로 더 나은 아이디어)을 사용 인코딩 codecs.open()하지 의 데이터를 직접 인코딩.


17

서문 : 시청자가 작동합니까?

뷰어 / 편집기 / 터미널 (utf-8로 인코딩 된 파일과 상호 작용하고 있음)이 파일을 읽을 수 있는지 확인하십시오. 이것은 메모장과 같은 Windows 에서 자주 발생하는 문제입니다 .

텍스트 파일에 유니 코드 텍스트를 작성 하시겠습니까?

Python 2에서는 모듈 open에서 사용 io합니다 ( openPython 3 의 기본 제공 기능과 동일 ).

import io

모범 사례는 일반적 UTF-8으로 파일에 쓰는 데 사용합니다 (utf-8의 바이트 순서에 대해 걱정할 필요조차 없음).

encoding = 'utf-8'

utf-8은 가장 현대적이고 보편적으로 사용 가능한 인코딩입니다. 모든 웹 브라우저, 대부분의 텍스트 편집기 (문제가있는 경우 설정 참조) 및 대부분의 터미널 / 쉘에서 작동합니다.

Windows에서는 utf-16le메모장 (또는 다른 제한된 뷰어)에서 출력보기로 제한되어 있으면 시도해 볼 수 있습니다 .

encoding = 'utf-16le' # sorry, Windows users... :(

컨텍스트 관리자로 열고 유니 코드 문자를 작성하십시오.

with io.open(filename, 'w', encoding=encoding) as f:
    f.write(unicode_object)

많은 유니 코드 문자를 사용하는 예

다음은 가능한 모든 문자를 최대 3 비트 (4는 최대이지만 조금 멀어 질 것입니다)에서 디지털 표현 (정수)에서 인코딩 된 인쇄 가능 출력 (이름과 함께)과 매핑하는 예제입니다. 가능합니다 (이 파일을 파일에 넣으십시오 uni.py) :

from __future__ import print_function
import io
from unicodedata import name, category
from curses.ascii import controlnames
from collections import Counter

try: # use these if Python 2
    unicode_chr, range = unichr, xrange
except NameError: # Python 3
    unicode_chr = chr

exclude_categories = set(('Co', 'Cn'))
counts = Counter()
control_names = dict(enumerate(controlnames))
with io.open('unidata', 'w', encoding='utf-8') as f:
    for x in range((2**8)**3): 
        try:
            char = unicode_chr(x)
        except ValueError:
            continue # can't map to unicode, try next x
        cat = category(char)
        counts.update((cat,))
        if cat in exclude_categories:
            continue # get rid of noise & greatly shorten result file
        try:
            uname = name(char)
        except ValueError: # probably control character, don't use actual
            uname = control_names.get(x, '')
            f.write(u'{0:>6x} {1}    {2}\n'.format(x, cat, uname))
        else:
            f.write(u'{0:>6x} {1}  {2}  {3}\n'.format(x, cat, char, uname))
# may as well describe the types we logged.
for cat, count in counts.items():
    print('{0} chars of category, {1}'.format(count, cat))

이 과정은 약 1 분 정도 걸리며 데이터 파일을 볼 수 있으며 파일 뷰어에서 유니 코드를 표시 할 수 있습니다. 범주에 대한 정보는 여기 에서 찾을 수 있습니다 . 카운트를 기준으로 Cn 및 Co 카테고리를 제외하면 결과가 향상 될 수 있습니다. Cn 및 Co 카테고리는 관련 기호가 없습니다.

$ python uni.py

16 진 맵핑, 카테고리를 표시합니다. , symbol (이름을 얻지 못하면 제어 문자) 및 기호 이름을 표시합니다. 예 :

less유닉스 또는 Cygwin을 권장 합니다 (전체 파일을 출력에 출력하지 마십시오).

$ less unidata

예를 들어 파이썬 2 (유니 코드 5.2)를 사용하여 샘플링 한 다음 줄과 유사하게 표시됩니다.

     0 Cc NUL
    20 Zs     SPACE
    21 Po  !  EXCLAMATION MARK
    b6 So    PILCROW SIGN
    d0 Lu  Ð  LATIN CAPITAL LETTER ETH
   e59 Nd    THAI DIGIT NINE
  2887 So    BRAILLE PATTERN DOTS-1238
  bc13 Lo    HANGUL SYLLABLE MIH
  ffeb Sm    HALFWIDTH RIGHTWARDS ARROW

Anaconda의 Python 3.5에는 유니 코드 8.0이 있으며 대부분 3을 가정합니다.


3

유니 코드 문자를 파일로 인쇄하는 방법 :

이것을 foo.py 파일에 저장하십시오 :

#!/usr/bin/python -tt
# -*- coding: utf-8 -*-
import codecs
import sys 
UTF8Writer = codecs.getwriter('utf8')
sys.stdout = UTF8Writer(sys.stdout)
print(u'e with obfuscation: é')

그것을 실행하고 출력을 파일로 파이프하십시오.

python foo.py > tmp.txt

tmp.txt를 열고 내부를 보면 다음과 같습니다.

el@apollo:~$ cat tmp.txt 
e with obfuscation: é

따라서 난독 화 표시가있는 유니 코드 e를 파일에 저장했습니다.


2
이 답변에 매우 흥분했지만 내 컴퓨터에 오류가 발생합니다. 코드를 복사 / 붙여 넣을 때 "TypeError : must be str, not not bytes"오류가 발생합니다.
Richard Rast

1

이 오류는 유니 코드가 아닌 문자열을 인코딩하려고 할 때 발생합니다. 일반 ASCII라고 가정하고 디코딩하려고 시도합니다. 두 가지 가능성이 있습니다.

  1. 바이트 문자열로 인코딩하고 있지만 codecs.open을 사용했기 때문에 write 메소드에는 유니 코드 객체가 필요합니다. 그래서 당신은 그것을 인코딩하고 그것을 다시 해독하려고합니다. 시험:f.write(all_html)대신 .
  2. all_html은 실제로 유니 코드 객체가 아닙니다. 당신이 할 때 .encode(...), 먼저 그것을 해독하려고 시도합니다.

0

python3으로 쓰는 경우

>>> a = u'bats\u00E0'
>>> print a
batsà
>>> f = open("/tmp/test", "w")
>>> f.write(a)
>>> f.close()
>>> data = open("/tmp/test").read()
>>> data
'batsà'

python2로 쓰는 경우 :

>>> a = u'bats\u00E0'
>>> f = open("/tmp/test", "w")
>>> f.write(a)

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xe0' in position 4: ordinal not in range(128)

이 오류를 피하려면 다음과 같이 "utf-8"코덱을 사용하여 바이트로 인코딩해야합니다.

>>> f.write(a.encode("utf-8"))
>>> f.close()

"utf-8"코덱을 사용하여 읽는 동안 데이터를 디코딩하십시오.

>>> data = open("/tmp/test").read()
>>> data.decode("utf-8")
u'bats\xe0'

또한이 문자열에서 인쇄를 실행하려고하면 다음과 같은 "utf-8"코덱을 사용하여 자동으로 디코딩됩니다.

>>> print a
batsà
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.