| ★ wanayoo — archive 1999 http://www.reportlab.com/i18n/python_unicode_tutorial.html | Nouvelle recherche | Portail wanayoo |
|
      |
Python Unicode TutorialThis is brief tutorial aimed at explaining the Unicode additions to Python. Please help me keep it up to date and accurate!Why is Python getting Unicode support?Once you get beyond the ASCII world, there are many different native encodings for different languages and operating systems. Converting between all of these is easiest with a central "common point", and that is Unicode. Unicode is a two-byte encoding which covers all of the world's common writing systems. It is important for many reasons:
Installation and SetupA Unicode-aware Python It is currently available in the public CVS repository; if you don't use CVS, you can get a nightly tar.gz or zip file.If you are used to using a compiled binary distribution of Python, such as the one on Windows, you need to make some potentially destructive changes to your existing environment. Here are some guidelines: (TODO) TODO - extract the diffs for the library - exceptions overwrite python.exe and pythonw.exe in C:\program files\python with the ones in the zip file if using Pythonwin, it won't start, as there is an illegal use of list.append() in the scintilla code, which Guido is going to ban for 1.6. Look in ..\python\pythonwin\pywin\scintilla\view.py lines 71 and 73, and add the extra brackets so they look like this:
event_commands.append((event, val))
for name, id in _extra_event_commands:
event_commands.append((name, id))
After this change, Pythonwin should work again.
Viewing data in different encodingsTo actually look at data in different encodings, the best tool is a web browser. You may not know it, but IE and Netscape can both display many common encodings (including Asian and Middle Eastern scripts, if you download the right fonts). The View | Encodings menu in IE5 controls how the current page is interpreted:![]() Let's imagine we have an HTML file containing the name of the author of the unicode extensions, encoded in ISO-latin-1. This contains an acute letter e, which is not available in ASCII. If you have this encoding selected in the browser, and have any Asian fonts installed, you should see this: ![]() If you now go and select (say) UTF8, the bytes will be interpreted differently and you will see this instead: ![]() That's because the three bytes from the acute-e to the 'L' in Lemburg are UTF8 for a Chinese character. (If you don't have the fonts installed, you'll see a round blob, which is the generic 'I don't know how to display this' symbol in IE5.) Seen from a long distance away, the Unicode extensions are largely about how to prevent this kind of thing: letting you explicitly control the encodings of the files you work with, and converting between them as needed. Unicode itself is an internal technology to make this easier. Basics about Unicode stringsCreating Unicode StringsWe'll run through a few snippets. The first is to look at the ways of creating Unicode strings. You can convert ASCII text to Unicode with a literal notation, prefixing a 'u' before the string. Unicode strings are printed to the console with a preceding 'u'.>>> u"Hello World!" #create a Unicode string u'Hello World!'To construct the string, Python assumed that the literal input was in UTF8, the "default encoding". UTF8 is a way of encoding Unicode such that the basic ASCII characters remain themselves; most other single-byte writing systems end up as two bytes; and Chinese characters end up as three bytes. Python 1.6 also gets a "unicode" built-in function, to which you can specify the encoding:
>>> unicode('hello')
u'hello'
>>> unicode('hello', 'ascii')
u'hello'
>>> unicode('hello', 'iso-8859-1')
u'hello'
>>>
All three of these return the same thing, since the characters in 'Hello' are common
to all three encodings.
Now let's encode something with a European accent, which is outside of ASCII. What you see at a console may depend on your operating system locale; Windows lets me type in ISO-Latin-1.
>>> a = unicode('André','latin-1')
>>> a
u'Andr\202'
If you can't type an acute letter e, you can enter the string 'Andr\202', which
is unambiguous.
Unicode supports all the common operations such as iteration and splitting. We won't run over them here. Encoding conversionsWe have seen how to construct a Unicode string. Now we can convert it to some other encoding using the encode() method as follows:
>>> a.encode('latin-1')
'Andr\202'
>>> print a.encode('latin-1')
André
>>> a.encode('utf8')
'Andr\302\202'
>>>
As we told you, the acute-e ends up as two bytes in the UTF8 encoding.
Not all conversions are possible because not every encoding includes every Unicode character. If we try to convert to ASCII, we should expect an error:
>>> a.encode('ascii')
Traceback (innermost last):
File "
There are three default error-handling modes which you can specify,
with the default being 'strict'; that way you will always be warned
about potential data loss.
>>> a.encode('ascii', 'strict') # the default, raise exception
Traceback (innermost last):
File "
Note that for the Asian encodings, we will try to provide user-settable
error behaviour going beyond this.
Looking at the raw dataSometimes you want to see how stuff is being stored internally. We deal with this using an 'encoding' called 'utf-16', which is actually pretty close to how the Unicode is stored internally. In fact, there are two flavours, 'utf-16-le' for little-endian machines and 'utf-16-be' for big-endian machines.
>>> a.encode('utf-16')
'\377\376A\000n\000d\000r\000\202\000'
>>>
The UTF16 standard specifies that 'naked' files or strings should be
preceded with a byte-order-mark to indicate the endianness of the
machine producing it, so UTF16 strings begin with 0xFFFE, or octal
\377\376 as we see above. Apart from that you can see ten bytes
>>> for char in a: ... print ord(char) ... 65 110 100 114 130 >>> Marc-Andre's original snippets
>>> u"Hello World!"
u'Hello World!'
>>> # Strings and Unicode do auto-coercion, e.g.
>>> u"Hello World!".split(u' ')
[u'Hello', u'World!']
>>> # This also works with normal strings:
>>> u"Hello World!".split(' ')
[u'Hello', u'World!']
>>> # Strings and Unicode can interoperate:
>>> 'Hello' + u' ' + 'World' + u'!'
u'Hello World!'
>>> # The string module handles both worlds using a single API
>>> import string
>>> string.split(u'Hello World!')
[u'Hello', u'World!']
>>> string.split('Hello World!')
['Hello', 'World!']
>>> # Using Codecs is easy:
>>> unicode('Hello World!','latin-1')
u'Hello World!'
>>> # ... in both directions:
>>> unicode('Hello World!','latin-1').encode('ascii')
'Hello World!'
>>> # The Unicode-Escape encoding simplifies entering Unicode
>>> # directly:
>>> u'Hello\u1234World!'
u'Hello\u1234World!'
>>> # Codecs raise a UnicodeError in case conversion is not
>>> # possible (note the center dot between the words):
>>> unicode('Hello·World!','latin-1').encode('ascii')
Traceback (innermost last):
File "
|