[Python-3000] Unicode and OS strings
Stephen J. Turnbull
stephen at xemacs.org
Sat Sep 15 02:13:31 CEST 2007
"Marcin 'Qrczak' Kowalczyk" <qrczak at knm.org.pl> writes:
>> And it *is* needed, because these characters by assumption
>> are not present in Unicode at all. (More precisely, they may be
>> present, but the tables we happen to have don't have mappings for
> They are present! For UTF-8, UTF-16 and UTF-32 PUA is not special in
> any way.
The characters I am referring to are the unstandardized so-called
"corporate characters" that are very common in Japanese text. My
solution handles your problem, slightly less efficiently than yours
does, perhaps, but in a Unicode-conforming way. Yours doesn't help
with mine at all.
> It preserves the byte string contents, which is all that is needed.
That is not true in any environment where the encoding is not known
> It has the same result as UTF-8 for all valid UTF-8 sequences not
> containing NUL.
Sorry, I'm talking about real Japanese and other situations where
there is no corresponding Unicode character point, and a solution
which not only handles that but also handles corrupt UTF-8. Valid
UTF-8 is not a problem, it's the solution. But a robust language
should handle text that is not valid UTF-8 in a way that allows the
programmer or user to implement error correction at a finer-grained
level than dumping core.
>> I'm also very bothered by the fact that the interpretation of U+0000
>> differs in different contexts in your proposal.
> Well, for any scheme which attempts to modify UTF-8 by accepting
> arbitrary byte strings is used, *something* must be interpreted
> differently than in real UTF-8.
Wrong. In my scheme everything ends up in the PUA, on which real
UTF-8 imposes no interpretation by definition.
I haven't gone back to check yet, but it's possible that a "real UTF-8
conforming process" is required to stop processing and issue an error
or something like that in the cases we're trying to handle. But your
extension and James Knight's extension both fall afoul of any such
>> Once you get a string into Python, you normally no longer know
>> where it came from, but now whether something came from the
>> program argument or environment or from a stdio stream changes the
>> semantics of U+0000. For me personally, that's a very good reason
>> to object to your proposal.
> This can be said about any modification of UTF-8.
It's not true of James Knight's proposal, because the same
modification can be used for both program arguments and file streams.
And my proposal doesn't modify UTF-8 at all; it takes advantage of the
farsighted wisdom of the designers of Unicode and puts all the
non-standard "characters", including broken encoding, in the PUA.
> Of course you can use such encoding on a standard stream too. In
> this case only U+0000 cannot be used normally, and the resulting
> stream will contain whatever bytes were present in filenames and
> other strings being output to it.
A programmer can use it, but his users will curse his name every time
a binary stream gets corrupted because they forgot that little detail.
>> > Of course my escaping scheme can preserve \0 too, by escaping it to
>> > U+0000 U+0000, but here it's incompatible with the real UTF-8.
>> No. It's *never* compatible with UTF-8 because it assigns a different
>> meaning to U+0000 from ASCII NUL.
> It is compatible with UTF-8 except for U+0000, and a true U+0000 cannot
> occur anyway in these contexts, so this incompatibility is mostly
Forcing users to use codecs of subtly different semantics simply because
they're getting I/O from different sources is a substantial harm.
>> Your scheme also suffers from the practical problem that strings
>> containing escapes are no longer arrays of characters.
> They are no less arrays of characters than strings containing combining
Those marks are characters in their own right. Your escapes are not,
nor are surrogates.
It's true that users will be surprised by the count of characters in
many cases with unnormalized Unicode, but these can be reduced to a
very few by normalizing to NFC.
More information about the Python-3000