Python 3.5, bytes, and %-interpolation (aka PEP 461)

Steven D'Aprano steve+comp.lang.python at pearwood.info
Mon Feb 24 18:55:36 EST 2014


On Tue, 25 Feb 2014 00:18:53 +0200, Marko Rauhamaa wrote:

> random832 at fastmail.us:
> 
>> On Mon, Feb 24, 2014, at 15:46, Marko Rauhamaa wrote:
>>> That is:
>>> 
>>>  1. ineffient (encode/decode shuffle)
>>> 
>>>  2. unnatural (strings usually have no place in protocols)
>>
>> That's not at all clear. Why _aren't_ these protocols considered text
>> protocols? Why can't you add a string directly to headers?

You cannot mix text strings and byte strings in Python 3. Python 2 allows 
you to do so, and it leads to hard-to-diagnose bugs and confusing 
behaviour. This is why Python 3 insists on a strict separation between 
the two.

But of course you can add *byte* strings directly to byte headers. Just 
prefix your strings with a b, as in b'Header' instead of 'Header', and it 
will work fine.

However, you don't really want to be adding large numbers of byte strings 
together, due to efficiency. Better to use % interpolation to insert them 
all at once. Hence the push to add % to bytes in Python 3.


Marko replied:
> Text expresses a written human language. In prosaic terms, a Python
> string is a sequence of ISO 10646 characters, whose codepoints are not
> octets.

Almost correct, but not quite. Python strings are Unicode, not ISO-10646. 
The two are not the same.

http://www.unicode.org/faq/unicode_iso.html


> Most network protocols are defined in terms of octets, although many of
> them can carry textual, audio or video payloads (among others). So when
> RFC 3507 (ICAP) shows an example starting:
> 
>    RESPMOD icap://icap.example.org/satisf ICAP/1.0 Host:
>    icap.example.org
>    Encapsulated: req-hdr=0, res-hdr=137, res-body=296
> 
> it consists of 8-bit octets and not some human language.

Not really relevant. In practical terms, whether they are implemented as 
octets or not, the sequence "Host" *is* human language, specifically it 
is the English word Host that just happens to be encoded in ASCII. 
Likewise the sequence "Encapsulated" *is* the English word Encapsulated 
encoded in ASCII.


> In practical terms, you get the bytes off the socket as, well, bytes. It
> makes little sense to "decode" those bytes into a string for
> manipulation. Manipulating bytes directly is both more efficient and
> more natural from the point of view of the standard.

But not necessarily more natural from the point of the programmer, which 
is what matters.

I agree that if you don't need to interpret the data as Unicode text, 
then there's no real benefit to decoding to text. (In fact, if your data 
can contain arbitrary bytes, you may not be able to decode to text, since 
not all byte sequences are legal UTF-8.)


> Many internet protocols happen to look like text. It makes it nicer for
> human network programmers to work with them. However, they are primarily
> meant for computers, and the message formats are really a form of binary
> code.

The reason that, say, the subject header line in emails starts with the 
word "Subject" rather than some arbitrary binary code is because it is 
intended to be human-readable. Not just human-readable, but *semantically 
meaningful*. That's why the subject line is labelled "Subject" rather 
than "Field 23" or "SJT".

Fortunately, such headers are usually (always?) ASCII, and byte strings 
in Python privilege ASCII-encoded text. When you write b'Subject', you 
get the same sequence of bytes as 'Subject'.encode('ascii').


-- 
Steven



More information about the Python-list mailing list