우리는 이미 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.name
UTF-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 string
unicode_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
. 악몽이야…