[Tutor] Converting a string to a byte array

Cameron Simpson cs at cskk.id.au
Sun Sep 24 17:26:55 EDT 2017


On 24Sep2017 20:24, Phil <phil_lor at bigpond.com> wrote:
>I'm trying to do the same under pyqt but I'm having trouble converting a 
>string to a byte array. This works correctly from the pyqt IDE but not from 
>the console. python3 mycode.py generates "typeError: string argument without 
>an encoding"

Is it possible your pyqt IDE is using Python 2 instead of Python 3. In Python 2 
strings are effectively byte arrays.

>It's very likely that my method of converting a string to a byte array 
>is incorrect. This is my attempt:
>
>mytext = "Fred"
>mybytes = bytes(mytext)
>byte = byte + '\n'
>ser.write(mybytes)

This can't be your code. I suspect the third line should be talking about 
"mybytes".

>I don't understand why this works from the pyqt IDE but not when run from the 
>console. I suppose the IDE is adding the correct encoding.

I'm guessing the IDE is python 2 and not doing any encoding at all. In python 2 
str _is_ effectively bytes and if you stay in ASCII you just get away with it.

>I suspect utf8 is involved somewhere.

In Python 3, strs contain Unicode code points, and when converting to bytes you 
need to specify how those code points are to be encoded, because a byte is 8 
bits wide, not enough to store most code points. So you need to "encode" the 
str into bytes.

So you need to know what your serial device expects. ASCII only? Some 8 bit 
coding like ISO8859-1 (covers a lotof Western Europe) or something else. For 
most modern environments the encoding will be UTF-8, but in serial environments 
that may not be the case depending on what is reading your data.

Anyway, if you're only using ASCII your ok, because the ISO8859 codings and 
UTF-8 use the _same_ encoding for pure ASCII as ASCII does (1 to 1, each byte 
holding a value from 0-127 becing the ASCII code). So you could try UTF-8 if 
you don't know what your serial device expects.

So:

  mytext = "Fred"
  mytext = mytext + "\n"
  mybytes = mytext.encode('utf-8')
  ser.write(mybytes)

Notice that I've appended the newline _before_ converting to bytes, while we're 
still talking about "text" (the stuff that goes in a str).

This will "just work". The risk is if your device can't cope with UTF-8.

If it turns out that your device expects something more constrained (eg ASCII) 
you can put 'ascii' where I have 'utf-8'. That has the advantage that your code 
will raise an exception if you feed in something outside ASCII, which your 
device wouldn't have coped with anyway. Look up the documentation for what your 
device expects. If the documentation is silent on this, maybe use 'ascii' 
instead just on principle - better to notice in your program and decide what to 
do there than to feed garbage to your device and have is misbehave.

Cheers,
Cameron Simpson <cs at cskk.id.au> (formerly cs at zip.com.au)


More information about the Tutor mailing list