[python] Python 2.6에서 unicode_literals를 사용하는 문제가 있습니까?

우리는 이미 Python 2.6에서 실행되는 코드베이스를 얻었습니다. Python 3.0을 준비하기 위해 다음을 추가하기 시작했습니다.

__future__에서 unicode_literals 가져 오기

우리로 .py파일 (우리가 그들을 수정으로). 나는 다른 누군가가 이것을하고 있고 분명하지 않은 문제가 발생했는지 궁금합니다 (아마도 많은 시간을 디버깅 한 후).



답변

내가 유니 코드 문자열로 작업 한 문제의 주요 원인은 utf-8 인코딩 문자열을 유니 코드 문자열과 혼합 할 때입니다.

예를 들어 다음 스크립트를 고려하십시오.

two.py

# encoding: utf-8
name = 'helló wörld from two'

one.py

# encoding: utf-8
from __future__ import unicode_literals
import two
name = 'helló wörld from one'
print name + two.name

실행의 출력 python one.py은 다음과 같습니다.

Traceback (most recent call last):
  File "one.py", line 5, in <module>
    print name + two.name
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 4: ordinal not in range(128)

이 예에서, two.nameUTF-8 인코딩 한 문자열 (유니 코드)는 가져 오지 않았기 때문에이다 unicode_literals, 그리고 one.name유니 코드 문자열입니다. 두 가지를 혼합하면 파이썬은 인코딩 된 문자열 (ascii라고 가정)을 디코딩하고이를 유니 코드로 변환하려고 시도하고 실패합니다. 당신이 그렇게한다면 그것은 작동 할 것 print name + two.name.decode('utf-8')입니다.

문자열을 인코딩하고 나중에 혼합하려고하면 동일한 일이 발생할 수 있습니다. 예를 들어 다음과 같이 작동합니다.

# encoding: utf-8
html = '<html><body>helló wörld</body></html>'
if isinstance(html, unicode):
    html = html.encode('utf-8')
print 'DEBUG: %s' % html

산출:

DEBUG: <html><body>helló wörld</body></html>

그러나 추가 한 후에는 import unicode_literals다음을 수행하지 않습니다.

# encoding: utf-8
from __future__ import unicode_literals
html = '<html><body>helló wörld</body></html>'
if isinstance(html, unicode):
    html = html.encode('utf-8')
print 'DEBUG: %s' % html

산출:

Traceback (most recent call last):
  File "test.py", line 6, in <module>
    print 'DEBUG: %s' % html
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 16: ordinal not in range(128)

'DEBUG: %s'은 유니 코드 문자열 이기 때문에 실패 하므로 파이썬은 디코딩을 시도합니다 html. 인쇄를 수정하는 몇 가지 방법은 print str('DEBUG: %s') % html또는 print 'DEBUG: %s' % html.decode('utf-8').

이것이 유니 코드 문자열을 사용할 때 잠재적 인 문제를 이해하는 데 도움이되기를 바랍니다.


답변

또한 2.6 (python 2.6.5 RC1 + 이전)에서는 유니 코드 리터럴이 키워드 인수 ( issue4978 ) 와 잘 어울리지 않습니다 .

예를 들어 다음 코드는 unicode_literals없이 작동하지만 TypeError : keywords must be stringunicode_literals가 사용되면 실패합니다 .

  >>> def foo(a=None): pass
  ...
  >>> foo(**{'a':1})
  Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
      TypeError: foo() keywords must be strings


답변

난 당신이 추가하면 찾을 않았다 unicode_literals지시를 당신은 또한 같은 것을 추가해야합니다 :

 # -*- coding: utf-8

.py 파일의 첫 번째 또는 두 번째 줄에. 그렇지 않으면 다음과 같은 줄이 있습니다.

 foo = "barré"

다음과 같은 오류가 발생합니다.

구문 오류 : 198 행의 mumble.py 파일에있는 비 ASCII 문자 '\ xc3',
 그러나 인코딩이 선언되지 않았습니다. http://www.python.org/peps/pep-0263.html 참조
 자세한 내용은


답변

또한 unicode_literal영향을 미치지는 eval()않지만 repr()(imho가 버그 인 비대칭 동작), 즉 (파이썬 3 에서처럼) eval(repr(b'\xa4'))같지 b'\xa4'않을 것임을 고려하십시오.

이상적으로 다음 코드는 모든 조합 unicode_literals및 Python {2.7, 3.x} 사용에 대해 항상 작동해야하는 고정 코드입니다 .

from __future__ import unicode_literals

bstr = b'\xa4'
assert eval(repr(bstr)) == bstr # fails in Python 2.7, holds in 3.1+

ustr = '\xa4'
assert eval(repr(ustr)) == ustr # holds in Python 2.7 and 3.1+

두 번째 주장 은 Python 2.7에서 repr('\xa4')평가 되기 때문에 작동 u'\xa4'합니다.


답변

더있다.

유니 코드를 허용하지 않는 문자열을 기대하는 라이브러리와 내장 기능이 있습니다.

두 가지 예 :

내장 :

myenum = type('Enum', (), enum)

(약간 esotic) unicode_literals에서 작동하지 않습니다 : type ()은 문자열을 기대합니다.

도서관:

from wx.lib.pubsub import pub
pub.sendMessage("LOG MESSAGE", msg="no go for unicode literals")

작동하지 않습니다 : wx pubsub 라이브러리는 문자열 메시지 유형을 예상합니다.

전자는 난해하고 쉽게 고정됩니다.

myenum = type(b'Enum', (), enum)

그러나 코드가 pub.sendMessage ()에 대한 호출로 가득 차 있다면 후자는 파괴적입니다.

젠장, 어?!?


답변

클릭from __future__ import unicode_literals 하면 사용하는 곳에서 가져온 모듈이있는 경우 모든 곳에서 유니 코드 예외가 발생합니다click.echo . 악몽이야…


답변