[Tutor] Error Python version 3.6 does not support this syntax.
Cameron Simpson
cs at cskk.id.au
Thu Nov 29 17:18:47 EST 2018
On 30Nov2018 02:19, srinivasan <srinivasan.rns at gmail.com> wrote:
>Thanks a lot for your quick responses, again the below line seems to
>be throwing the same error, is that should I again decode the line
>where am facing the issue to str? or could you please let me if there
>is any alternative solution for the same or workaround in python 3.6?
>
>Code Snippet:
>
> def parse_device_info(self, info_string):
> """Parse a string corresponding to a device."""
> device = {}
> block_list = ["[\x1b[0;", "removed"]
> string_valid = not any(keyword in info_string for keyword in
>block_list) ---------------------------> Again this line seems to be
>the same issue
[...]
> def get_paired_devices(self):
> """Return a list of tuples of paired devices."""
> try:
> out = self.get_output("paired-devices")
> except BluetoothctlError as e:
> print(e)
> return None
> else:
> paired_devices = []
> for line in out:
> device = self.parse_device_info(line)
[...]
Your problem is basicly that reading from command output gets you bytes
data, not text (str) data. This is because pipes transfer bytes; that
the command may issue text simply means that those bytes are an encoding
of the text.
Your entire process treats the output as text, because the commands
issue textual output.
Therefore, the most sensible thing to do at this point is to _decode_
the bytes into text as soon as you get them from the command, and then
the rest of your programme can work in text (str) from then on.
So I would be inclined to change:
for line in out:
device = self.parse_device_info(line)
into (untested):
for line_b in out:
line = line_b.decode(errors='replace')
device = self.parse_device_info(line)
That will turn line_b (a bytes object holding the line) into text before
you try to do any parsing. From that point onward, everything is text
(str) and you do not need to put any bytes->str stuff elsewhere in your
programme.
Some remarks:
That decode line above uses the default bytes->str decoding, which is
'utf-8'. That is probably how your system works, but if it is not you
need to adjust accordingly. If the command ussues pure ASCII you'll be
fine regardless.
The decode uses "errors='replace'", which means that if the bytes data
are _not_ correct UTF-8 encoded text, the decoder will put some
replacement characters in the result instead of raising an exception.
This simplifies your code, and since you're parsing the output anyway
for infomation the replacements should show up to your eye. The default
decode mode is 'strict', which would raise an exception on an invalid
encoding.
Purists might decode the output stream ("out") before the for-loop, but
in most encodings including UTF-8, you can split on newlines (byte code
10, ASCII NL) safely anyway, so we just split first and decode each
"bytes" line individually.
In the loop I deliberately iterate over "line_b", and have the decoded
text in "line", instead of doing something like:
for line in out:
line = line.decode(....)
That way I am always sure that I intend to talk about bytes in one place
(line_b) and text (line) in another. Having variable that might contain
bytes _or_ text leads to confusion and difficult debugging.
The core takeaway here is that you want to keep in mind whether you're
working in bytes or text (str). Keep the division clean, that way all
you other code can be written appropriately. So: the command pipe output
is bytes. COnvert it to text before passing to your text parsing code.
That way all the parsing code can work in text (str) and have no weird
conversion logic.
Cheers,
Cameron Simpson <cs at cskk.id.au>
More information about the Python-list
mailing list