Hi @Merlin513.
Unfortunately the Spidev Python package has a lot of dependencies. The cause of the error is that these dependencies are not present in the Docker container in which the App's Python script runs. You would need to install them in the container.
There are a lot of advantages to using containers. However, it also introduces extra complexity to an endeavor. So if you are only interested in general experimentation, your alternative approach of working directly in the standard Linux machine of the UNO Q might be the best place to start. Once you achieve success in that environment, you could use what you learned to set up a container.
When you run an App, it creates a virtual Python dependencies environment inside the Docker container in which the Python script component of the App runs. So if you are trying to work in the standard environment of the UNO Q's Linux machine, you will not have any success trying to use the App to generate an environment. You should instead generate the environment directly.
I would normally recommend using my favorite tool, Poetry for this purpose. However, the tool chosen by the developers of the Arduino App framework is uv. It makes sense to utilize the same tool used in the App's container, and I believe this is actually more lightweight than Poetry, and thus well suited for use on the UNO Q where we must conserve our use of computing resources.
So let's start by installing uv:
https://docs.astral.sh/uv/getting-started/installation/
I used this method:
curl -LsSf https://astral.sh/uv/install.sh | sh && source $HOME/.local/bin/env
Now create a uv project:
uv init ~/spidevtest && cd ~/spidevtest
Now we would expect to be able to install the project's package dependencies via uv add. However, if we try to do this for the spidev package, we encounter the same type of problem of missing dependencies:
$ uv add spidev
Using CPython 3.13.5 interpreter at: /usr/bin/python3.13
Creating virtual environment at: .venv
Resolved 2 packages in 558ms
× Failed to build `spidev==3.8`
├─▶ The build backend returned an error
╰─▶ Call to `setuptools.build_meta.build_wheel` failed (exit status: 1)
[stdout]
running bdist_wheel
running build
running build_ext
building 'spidev' extension
creating build/temp.linux-aarch64-cpython-313
aarch64-linux-gnu-gcc -fno-strict-overflow -Wsign-compare -DNDEBUG -g -O2 -Wall -fPIC -I/home/arduino/.cache/uv/builds-v0/.tmp42K2yj/include -I/usr/include/python3.13 -c spidev_module.c -o build/temp.linux-aarch64-cpython-313/spidev_module.o
[stderr]
/home/arduino/.cache/uv/builds-v0/.tmp42K2yj/lib/python3.13/site-packages/setuptools/dist.py:765: SetuptoolsDeprecationWarning: License classifiers are deprecated.
!!
********************************************************************************
Please consider removing the following classifiers in favor of a SPDX license expression:
License :: OSI Approved :: MIT License
See https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#license for details.
********************************************************************************
!!
self._finalize_license_expression()
error: command 'aarch64-linux-gnu-gcc' failed: No such file or directory
hint: This usually indicates a problem with the package or the build environment.
help: If you want to add the package regardless of the failed resolution, provide the `--frozen` flag to skip locking and syncing.
It seems like the logical next step is installing GCC, which I did like so:
sudo apt install gcc-aarch64-linux-gnu
I then had another go at installing the spidev package:
$ uv add spidev
Resolved 2 packages in 13ms
× Failed to build `spidev==3.8`
├─▶ The build backend returned an error
╰─▶ Call to `setuptools.build_meta.build_wheel` failed (exit status: 1)
[stdout]
running bdist_wheel
running build
running build_ext
building 'spidev' extension
aarch64-linux-gnu-gcc -fno-strict-overflow -Wsign-compare -DNDEBUG -g -O2 -Wall -fPIC -I/home/arduino/.cache/uv/builds-v0/.tmpYCinb5/include -I/usr/include/python3.13 -c spidev_module.c -o build/temp.linux-aarch64-cpython-313/spidev_module.o
[stderr]
/home/arduino/.cache/uv/builds-v0/.tmpYCinb5/lib/python3.13/site-packages/setuptools/dist.py:765: SetuptoolsDeprecationWarning: License classifiers are deprecated.
!!
********************************************************************************
Please consider removing the following classifiers in favor of a SPDX license expression:
License :: OSI Approved :: MIT License
See https://packaging.python.org/en/latest/guides/writing-pyproject-toml/#license for details.
********************************************************************************
!!
self._finalize_license_expression()
spidev_module.c:28:10: fatal error: Python.h: No such file or directory
28 | #include <Python.h>
| ^~~~~~~~~~
compilation terminated.
error: command '/usr/bin/aarch64-linux-gnu-gcc' failed with exit code 1
hint: This error likely indicates that you need to install a library that provides "Python.h" for `spidev@3.8`
help: If you want to add the package regardless of the failed resolution, provide the `--frozen` flag to skip locking and syncing.
Looks like progress, but not success. I next tried this:
sudo apt install python3-dev
Then another attempt at spidev:
$ uv add spidev
[...]
aarch64-linux-gnu-gcc: fatal error: cannot execute ‘as’: posix_spawnp: No such file or directory
compilation terminated.
error: command '/usr/bin/aarch64-linux-gnu-gcc' failed with exit code 1
hint: This usually indicates a problem with the package or the build environment.
Looks like more progress, but not success. I next tried this:
sudo apt install binutils
Now another try for spidev:
$ uv add spidev
Resolved 2 packages in 14ms
Built spidev==3.8
Prepared 1 package in 6.12s
Installed 1 package in 4ms
+ spidev==3.8
Success!
Next it is time to try using the thing. I'll create a minimal script:
echo 'import spidev
spi = spidev.SpiDev()
spi.open_path("/dev/spidev0.0")
spi.writebytes([1])
spi.close()' \
> spidevtest.py
Now run the script:
$ uv run spidevtest.py
Traceback (most recent call last):
File "/home/arduino/spidev-test/spidevtest.py", line 3, in <module>
spi.open_path("/dev/spidev0.0")
~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^
PermissionError: [Errno 13] Permission denied
The problem is that the user account does not have write permission for /dev/spidev0.0. The modern way to manage these permissions is through udev rules:
The arduino user is automatically included in the gpiod user group:
$ groups
arduino adm dialout sudo audio video users netdev bluetooth docker sysupgrade render input gpiod
For the sake of simplicity, I'll use that existing group in this udev rule:
$ echo \
'# See: https://github.com/doceme/py-spidev/blob/v3.8/99-local-spi-example-udev.rules#L31
KERNEL=="spidev*", GROUP="gpiod", MODE="0660"' \
| \
sudo \
tee \
"/etc/udev/rules.d/60-spi.rules" \
&& \
sudo \
udevadm control \
--reload-rules \
&& \
sudo \
udevadm trigger
$ sudo groupadd spi
$ sudo usermod --append --groups spi arduino
Now run the script once again:
$ uv run spidevtest.py && echo $?
Looks like success!
I didn't go beyond that to verify communication with sketch on the microcontroller, but hopefully this will be enough to allow you to progress at least.
All the above is simply me sharing the results from my fumbling trial and error. It might well be that there is a better/correct way to go about this. Others are of course very welcome to suggest corrections or improvements on what I did.