0

I moved my python scripts from 2.7 to 3 using 2to3 module, and now I am trying them out...Can some explain what I need to change here?

found_qr = None
while not found_qr:
    keep_alive(1,5)
    time.sleep(4)
    process = None
    stdout_list = None
    process = subprocess.Popen('grep -E -o ".Source QR CODE :.{0,65}" ' + latest_file + ' | tail -1', shell=True, stdout=subprocess.PIPE,)
    stdout_list = process.communicate()
    stdout_list = stdout_list[0]
    if stdout_list.find("Source QR CODE") == -1:
        found_qr = None
    else:
        found_qr = 'found!'

I am getting this error:

if stdout_list.find("Source QR CODE") == -1:
TypeError: argument should be integer or bytes-like object, not 'str'

any idea? thanks!

Update: Here is a similar issue I am seeing:

keep_alive(1,1)
process = subprocess.Popen('grep -E -o ".Source QR CODE :.{0,65}" ' + latest_file + ' | tail -1', shell=True, stdout=subprocess.PIPE,)
stdout_list = process.communicate()
qr_code = stdout_list[0].replace('Source QR CODE : ','')
qr_code = qr_code.replace(' ','')
qr_code = qr_code.replace('\n', '')
qr_code = str(qr_code)

TypeError: a bytes-like object is required, not 'str'

cjg123
  • 473
  • 7
  • 23

1 Answers1

1

In stdout_list = process.communicate() you get a list of bytes, so stdout_list[0] is a bytes object.

In stdout_list.find("Source QR CODE") you're trying to find a string in this bytes object, which won't work because bytes is different from str in Python 3.

Since this string is constant, you can convert it to a bytes object easily:

stdout_list.find(b"Source QR CODE")  # note the `b` before the string literal

Or encode this string appropriately:

stdout_list.find("Source QR CODE".encode('ascii'))  # here you can use whatever encoding you need

As the error message tells you, you can search for "bytes-like objects" and integers, because a bytes object is actually a list of integers from 0 to 255:

>>> b'thing'  # this is a bytes object
b'thing'
>>> list(_)
[116, 104, 105, 110, 103]  # actually a bunch of integers (bytes)
>>> b'thing'.find(116)  # find a single byte
0
ForceBru
  • 43,482
  • 10
  • 63
  • 98
  • That seems to have worked...but can you help with this (similar issue): process = subprocess.Popen('grep -E -o ".Source QR CODE :.{0,65}" ' + latest_file + ' | tail -1', shell=True, stdout=subprocess.PIPE,) stdout_list = process.communicate() qr_code = stdout_list[0].replace('Source QR CODE : ','') qr_code = qr_code.replace(' ','') qr_code = qr_code.replace('\n', '') qr_code = str(qr_code) – cjg123 Feb 03 '20 at 18:08
  • 1
    @cjg123, you can run your code through [`2to3`](https://docs.python.org/3.8/library/2to3.html) first. It should convert most of the code to Python 3 automatically – ForceBru Feb 03 '20 at 18:11
  • I did, but a lot of it was not changed...why would that be? – cjg123 Feb 03 '20 at 18:15
  • 1
    @cjg123, well, it's not perfect. For example, it doesn't seem to be able to infer that `stdout_list` is a `bytes` object. Anyway, for each error message of this kind, you should add a prefix `b` to each string literal in that line. For example: `qr_code = stdout_list[0].replace('Source QR CODE : ','')` -> `qr_code = stdout_list[0].replace(b'Source QR CODE : ', b'')` – ForceBru Feb 03 '20 at 18:18
  • yeah, I just did that and it appears to be working. Thank you for your help (and yeah, it does not appear to be a perfect system, but a decent starting point). – cjg123 Feb 03 '20 at 18:19
  • Question: I am now being returned this in the 2nd part b'a,555.55.7.38,22222,device-lab,..!1wdf336F3tN*' ... whereas before I would just get back a string...Why? – cjg123 Feb 03 '20 at 18:53
  • 1
    @cjg123, actually, `qr_code = str(qr_code)` will result in `"b'thing'"`, not just `b'thing'`. Why? Well, Python did what you asked it to do - it returned the string _representation_ of that `bytes` object - the `"b'thing'"`, while you expected just `"thing"`, _but_ that would be a different operation - [decoding](https://docs.python.org/3/library/stdtypes.html#bytes.decode). – ForceBru Feb 03 '20 at 18:57