Re: [Tutor] Error Python version 3.6 does not support this syntax.
On Fri, Nov 30, 2018 at 02:19:25AM +0530, srinivasan wrote: > Dear Mats, > > 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? You don't need a "workaround", you need to fix the bug in your code: > Traceback (most recent call last): > , in parse_device_info > string_valid = not any(keyword in info_string for keyword in block_list) > File "/home/srinivasan/Downloads/bt_tests/qa/test_library/bt_tests.py", > line 52, in > string_valid = not any(keyword in info_string for keyword in block_list) > TypeError: a bytes-like object is required, not 'str' You get that error when you wrongly try to test for a string inside a bytes object: py> 'string' in b'bytes' Traceback (most recent call last): File "", line 1, in TypeError: a bytes-like object is required, not 'str' You fix that by making sure both objects are strings, or both are bytes, which ever is better for your program: py> 'a' in 'abc' # string in string is okay True py> b'a' in b'abc' # bytes in bytes is okay True py> 'a' in b'abc' # string in bytes is NOT OKAY Traceback (most recent call last): File "", line 1, in TypeError: a bytes-like object is required, not 'str' py> b'a' in 'abc' # bytes in string is NOT OKAY Traceback (most recent call last): File "", line 1, in TypeError: 'in ' requires string as left operand, not bytes Don't mix strings and bytes. It won't work. -- Steve ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Error Python version 3.6 does not support this syntax.
Dear Mats, 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 if string_valid: try: device_position = info_string.index("Device") except ValueError: pass else: if device_position > -1: attribute_list = info_string[device_position:].split(" ", 2) device = { "mac_address": attribute_list[1], "name": attribute_list[2] } return device 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) if device: paired_devices.append(device) return paired_devices if __name__ == "__main__": print("Init bluetooth...") bl = Bluetoothctl() print("Ready!") bl.start_scan() print("Scanning for 10 seconds...") for i in range(0, 10): print(i) time.sleep(1) bl.pair("64:A2:F9:06:63:79") print("Pairing for 10 seconds...") for i in range(0, 10): print(i) time.sleep(1) # Seems to be an issue -- bl.get_paired_devices() print("Getting Paired devices for 10 seconds...") for i in range(0, 10): print(i) time.sleep(1) Error Logs: Traceback (most recent call last): , in parse_device_info string_valid = not any(keyword in info_string for keyword in block_list) File "/home/srinivasan/Downloads/bt_tests/qa/test_library/bt_tests.py", line 52, in string_valid = not any(keyword in info_string for keyword in block_list) TypeError: a bytes-like object is required, not 'str' On Fri, Nov 30, 2018 at 1:18 AM Mats Wichmann wrote: > > On 11/29/18 12:20 PM, srinivasan wrote: > > Dear Python Experts, > > > > With the below code snippet, I am seeing the below error, I am using > > python 3.6, could you please what could be the issue? > > > self.child = pexpect.spawn("bluetoothctl", echo = False) > ... > > self.child.send(command + "\n") > > time.sleep(pause) > > start_failed = self.child.expect(["bluetooth", pexpect.EOF]) > ... > > return self.child.before.split("\r\n") > > ---> > > the issue seems to be here > > line 27, in get_output > > return self.child.before.split("\r\n") > > TypeError: a bytes-like object is required, not 'str' > > your types don't match. it's Python 3 so what you get back from talking > to an external process is a bytes object. you're calling the split > method on that object, but passing it a string to split on - that's what > the error is saying. It shouldn't be any more complicated to fix that > than to give it a byte object: > > return self.child.before.split(b"\r\n") > > or... decode the object to a str before splitting on a string. > > but since you're specifically splitting on lines, you may as well use > the splitlines method instead of the split method, since that's what it > is designed for. > > > > > ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Error Python version 3.6 does not support this syntax.
Dear Python Experts, With the below code snippet, I am seeing the below error, I am using python 3.6, could you please what could be the issue? Code Snippet: --- import time import pexpect import subprocess import sys class BluetoothctlError(Exception): """This exception is raised, when bluetoothctl fails to start.""" pass class Bluetoothctl: """A wrapper for bluetoothctl utility.""" def __init__(self): out = subprocess.check_output("rfkill unblock bluetooth", shell = True) self.child = pexpect.spawn("bluetoothctl", echo = False) def get_output(self, command, pause = 0): """Run a command in bluetoothctl prompt, return output as a list of lines.""" self.child.send(command + "\n") time.sleep(pause) start_failed = self.child.expect(["bluetooth", pexpect.EOF]) if start_failed: raise BluetoothctlError("Bluetoothctl failed after running " + command) return self.child.before.split("\r\n") ---> the issue seems to be here def start_scan(self): """Start bluetooth scanning process.""" try: out = self.get_output("scan on") except BluetoothctlError as e: print(e) return None if __name__ == "__main__": print("Init bluetooth...") bl = Bluetoothctl() print("Ready!") bl.start_scan() print("Scanning for 10 seconds...") for i in range(0, 10): print(i) time.sleep(1) Error Logs: - /home/srinivasan/Downloads/bt_tests/qa/venv/bin/python /home/srinivasan/Downloads/bt_tests/qa/test_library/bt_tests.py Init bluetooth... Ready! Traceback (most recent call last): File "/home/srinivasan/Downloads/bt_tests/qa/test_library/bt_tests.py", line 169, in bl.start_scan() File "/home/srinivasan/Downloads/bt_tests/qa/test_library/bt_tests.py", line 32, in start_scan out = self.get_output("scan on") File "/home/srinivasan/Downloads/bt_tests/qa/test_library/bt_tests.py", line 27, in get_output return self.child.before.split("\r\n") TypeError: a bytes-like object is required, not 'str' Process finished with exit code 1 On Wed, Nov 28, 2018 at 12:17 AM Mats Wichmann wrote: > > On 11/27/18 5:50 AM, srinivasan wrote: > > Dear Python Experts, > > > > As still I am newbie and learning python, I am trying to reuse the > > Bluetoothctl wrapper in Python from the link ( > > https://gist.github.com/egorf/66d88056a9d703928f93) I am using python3.6 > > version, In pycharm editor on the bold highlighted code snippets I see the > > error message "Python version 3.6 does not support this syntax.", > > once again you've posted in a way that inserts lots of extra crud, you > avoided that last time. > > The syntax change is simple (and works on most older Pythons too): > > except ErrorType, e: > > becomes > > except ErrorType as e: > > > > > > Could you please how help me how the below highlighted lines of code can be > > can be ported to python3.6 version? > > > > *except BluetoothctlError, e:* > > > > *print(e)* > > *return None* > > ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Error Python version 3.6 does not support this syntax.
On 30Nov2018 02:19, srinivasan 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 ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Error Python version 3.6 does not support this syntax.
On 11/29/18 12:20 PM, srinivasan wrote: > Dear Python Experts, > > With the below code snippet, I am seeing the below error, I am using > python 3.6, could you please what could be the issue? > self.child = pexpect.spawn("bluetoothctl", echo = False) ... > self.child.send(command + "\n") > time.sleep(pause) > start_failed = self.child.expect(["bluetooth", pexpect.EOF]) ... > return self.child.before.split("\r\n") > ---> > the issue seems to be here > line 27, in get_output > return self.child.before.split("\r\n") > TypeError: a bytes-like object is required, not 'str' your types don't match. it's Python 3 so what you get back from talking to an external process is a bytes object. you're calling the split method on that object, but passing it a string to split on - that's what the error is saying. It shouldn't be any more complicated to fix that than to give it a byte object: return self.child.before.split(b"\r\n") or... decode the object to a str before splitting on a string. but since you're specifically splitting on lines, you may as well use the splitlines method instead of the split method, since that's what it is designed for. ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
Re: [Tutor] Error Python version 3.6 does not support this syntax.
On 11/27/18 5:50 AM, srinivasan wrote: > Dear Python Experts, > > As still I am newbie and learning python, I am trying to reuse the > Bluetoothctl wrapper in Python from the link ( > https://gist.github.com/egorf/66d88056a9d703928f93) I am using python3.6 > version, In pycharm editor on the bold highlighted code snippets I see the > error message "Python version 3.6 does not support this syntax.", once again you've posted in a way that inserts lots of extra crud, you avoided that last time. The syntax change is simple (and works on most older Pythons too): except ErrorType, e: becomes except ErrorType as e: > > Could you please how help me how the below highlighted lines of code can be > can be ported to python3.6 version? > > *except BluetoothctlError, e:* > > *print(e)* > *return None* > ___ Tutor maillist - Tutor@python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor
[Tutor] Error Python version 3.6 does not support this syntax.
Dear Python Experts, As still I am newbie and learning python, I am trying to reuse the Bluetoothctl wrapper in Python from the link ( https://gist.github.com/egorf/66d88056a9d703928f93) I am using python3.6 version, In pycharm editor on the bold highlighted code snippets I see the error message "Python version 3.6 does not support this syntax.", Could you please how help me how the below highlighted lines of code can be can be ported to python3.6 version? *except BluetoothctlError, e:* *print(e)* *return None* Full Code snippet: == import time import pexpect import subprocess import sys class BluetoothctlError(Exception): """This exception is raised, when bluetoothctl fails to start.""" pass class Bluetoothctl: """A wrapper for bluetoothctl utility.""" def __init__(self): out = subprocess.check_output("rfkill unblock bluetooth", shell = True) self.child = pexpect.spawn("bluetoothctl", echo = False) def get_output(self, command, pause = 0): """Run a command in bluetoothctl prompt, return output as a list of lines.""" self.child.send(command + "\n") time.sleep(pause) start_failed = self.child.expect(["bluetooth", pexpect.EOF]) if start_failed: raise BluetoothctlError("Bluetoothctl failed after running " + command) return self.child.before.split("\r\n") def start_scan(self): """Start bluetooth scanning process.""" try: out = self.get_output("scan on") *except BluetoothctlError, e:print(e)return None* def make_discoverable(self): """Make device discoverable.""" try: out = self.get_output("discoverable on") * except BluetoothctlError, e:print(e)return None* 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) if string_valid: try: device_position = info_string.index("Device") except ValueError: pass else: if device_position > -1: attribute_list = info_string[device_position:].split(" ", 2) device = { "mac_address": attribute_list[1], "name": attribute_list[2] } return device def get_available_devices(self): """Return a list of tuples of paired and discoverable devices.""" try: out = self.get_output("devices") *except BluetoothctlError, e:print(e)return None* else: available_devices = [] for line in out: device = self.parse_device_info(line) if device: available_devices.append(device) return available_devices def get_paired_devices(self): """Return a list of tuples of paired devices.""" try: out = self.get_output("paired-devices") *except BluetoothctlError, e:print(e)return None* else: paired_devices = [] for line in out: device = self.parse_device_info(line) if device: paired_devices.append(device) return paired_devices def get_discoverable_devices(self): """Filter paired devices out of available.""" available = self.get_available_devices() paired = self.get_paired_devices() return [d for d in available if d not in paired] def get_device_info(self, mac_address): """Get device info by mac address.""" try: out = self.get_output("info " + mac_address) *except BluetoothctlError, e:print(e)return None* else: return out def pair(self, mac_address): """Try to pair with a device by mac address.""" try: out = self.get_output("pair " + mac_address, 4) *except BluetoothctlError, e:print(e)return None* else: res = self.child.expect(["Failed to pair", "Pairing successful", pexpect.EOF]) success = True if res == 1 else False return success def remove(self, mac_address): """Remove paired device by mac address, return success of the operation.""" try: out = self.get_output("remove " + mac_address, 3) *except BluetoothctlError, e:print(e)return None* else: res = self.child.expect(["not available", "Device has been removed", pexpect.EOF]) success = True if res == 1 else False return