arvydas / blinkstick-python

BlinkStick Python interface to control devices connected to the computer
Other
136 stars 53 forks source link

[Solution Workaround] Python 3.9.2 - IndexError: array index out of range #77

Open gregnrobinson opened 2 years ago

gregnrobinson commented 2 years ago

Blinkstick is having problems with python 3.9.2. I installed the latest version of Raspian (Debian Bullseye) and it ships with 3.9.2. On the other nodes, I was using <=3.8.2 so installed python 3.8.2 on Debian and got it to work using the steps below.

the issue appears when executing blinkstick using sudo blinkstick. This is essentially a workaround using a workaround because even with Python 3.8 there are problems which are outlined in this issue. Shown below is the output on each version followed by steps to get it working on your system using Python 3.8. I think even using Python 3.7 would just work out of the box without the extra steps...

Python 3.9 Output

pi@kube1:~/python38-env $ python3 --version
Python 3.9.2

pi@kube1:~/python38-env $ sudo blinkstick --blink green
Traceback (most recent call last):
  File "/usr/local/bin/blinkstick", line 331, in <module>
    sys.exit(main())
  File "/usr/local/bin/blinkstick", line 220, in main
    sticks = blinkstick.find_all()
  File "/usr/local/lib/python3.9/dist-packages/blinkstick/blinkstick.py", line 1566, in find_all
    result.extend([BlinkStick(device=d)])
  File "/usr/local/lib/python3.9/dist-packages/blinkstick/blinkstick.py", line 217, in __init__
    self.bs_serial = self.get_serial()
  File "/usr/local/lib/python3.9/dist-packages/blinkstick/blinkstick.py", line 283, in get_serial
    return self._usb_get_string(self.device, 3)
  File "/usr/local/lib/python3.9/dist-packages/blinkstick/blinkstick.py", line 221, in _usb_get_string
    return usb.util.get_string(device, index, 1033)
  File "/usr/local/lib/python3.9/dist-packages/usb/util.py", line 260, in get_string
    return buf[2:buf[0]].tostring().decode('utf-16-le')
IndexError: array index out of range

Python 3.8 Output

pi@kube1:~/python38-env $ source ./bin/activate
(python38-env) pi@kube1:~/python38-env $ python --version
Python 3.8.2

Change file /usr/local/bin/blinkstick interpretor from #!/usr/bin/env python to #!/home/pi/python38-env/bin/python3

(python38-env) pi@kube1:~/python38-env $ head -5 /usr/local/bin/blinkstick
#!/home/pi/python38-env/bin/python3

from optparse import OptionParser, IndentedHelpFormatter, OptionGroup
from blinkstick import blinkstick

Run sudo blinkstick --blink green

(python38-env) pi@kube1:~/python38-env $ sudo blinkstick --blink green
(python38-env) pi@kube1:~/python38-env $

Install Blinkstick inside Python 3.8 virtual environment

Create Python 3.8 virtual environment

# Install python 3.8 on debian: https://linuxize.com/post/how-to-install-python-3-8-on-debian-10/

mkdir ~/python38-env && cd ~/python38-env
python3.8 -m venv .
source ./bin/activate

Perform Python 3.8 workaround steps

sudo apt-get install dos2unix
pip install pyusb
pip install blinkstick
sudo chmod +x /usr/local/bin/blinkstick

Change python interpretor for blinktick module

Note: In my case I used python38-env as the target folder when creating the virtual env in the early steps.

By changing the interpreter in the module directly will allow Blinkstick to function when the virtual env is deactivated.

#!/usr/bin/env python to #!/home/pi/python38-env/bin/python3

Run sudo blinkstick and you should see the help menu.

Running sudo blinkstick --blink green works on the host.

Reference

Install Python 3.8 on Debian 10: https://linuxize.com/post/how-to-install-python-3-8-on-debian-10/ Install Python 3.8 on Debian 11: https://www.linuxcapable.com/how-to-install-python-3-8-on-debian-11-bullseye/ I used the Debian 10 tutorial for installing on bullseye but then found this version. Looks like it installs 3.8.12 instead of 3.8.2 Python 3.8 workaround reference: https://github.com/arvydas/blinkstick-python/issues/34

gregnrobinson commented 2 years ago

Here is a successful pipeline run after applying the workaround. kube1 was the node with Python 3.9.2.

https://github.com/gregnrobinson/blinkstick-ansible/runs/4479396388?check_suite_focus=true

JuliaPageMorseMicro commented 9 months ago

I had a similar problem (using Python 3.10.5) in the same scenario where I was obliged to be the root user.

I pursued it as far as /usr/lib/python3.10/site-packages/usb/util.py:get_string where the read of langid successfully returned 0x409 (1033) which is "English (US)" but then the immediate next read which was supposed to be of the serial string returned zero bytes where 3 were expected.

I eventually found that after updating pyusb-1.0.0 to pyusb-1.2.1, the problem went away.