Will Murphy's personal home page

Django Raspberry Pi

EDIT FROM THE FUTURE!
Some of the troubleshooting attempts in this post only seemed to work. In other words, they got me to a better error message (yay!) but then when I tried to progress, I had to go back and to re-work (boo!). Please see my next post in the series for details.

We’re trying to deploy a django app to a Raspberry Pi this week!

There are a few things we need to wire up to make this work:

  1. Get our python code onto the Pi.
  2. Get the dependencies installed on the Pi.
  3. Configure apache webserver to forward requests to django.
  4. Set up a database
  5. Probably other things I haven’t thought of yet.

Step 1: Get our code onto the Pi

For this, we just used rsync. Here’s the specific command:

rsync -r . pi@raspberrypi:/home/pi/pidjango

Eventually, I might rather use some automation here, or go through git. But to just get it working, rsync is a reasonable start.

Step 2: Install dependencies

I tried creating a virtual env and running python3 -m pip install ., in order to get the dependencies from my pyproject.toml installed, but this failed with an error:

$ python3 -m pip install .
Looking in indexes: https://pypi.org/simple, https://www.piwheels.org/simple
Processing /home/pi/pidjango
  Installing build dependencies ... done
    Complete output from command python setup.py egg_info:
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "/usr/lib/python3.7/tokenize.py", line 447, in open
        buffer = _builtin_open(filename, 'rb')
    FileNotFoundError: [Errno 2] No such file or directory: '/tmp/pip-req-build-izgt0lqo/setup.py'

I’ve tried searching online for this error, but there’s not much of a stacktrace, and there are literally a million things that will give you FileNotFoundError, so it’s really not the most helpful error. The only surprising thing in the output is that python3.7, which makes me think that we’re dealing with a super old python3 install. Sure enough:

$ python3 --version
Python 3.7.3

So now let’s try to install a modern python3, on the assumption that the reason dependencies are missing files is that some module was added after Python 3.7.3 that we need.

Step 2A: Install recent Python3

EDIT FROM THE FUTURE!
This is the part that didn’t work. Instead of adding a new python, I should have done a full upgrade of the Pi, since Apache2’s mod_wsgi links against libpython. More on that in the next post in the series.

I tried just using the package manager:

$ sudo apt-get install python3
Reading package lists... Done
Building dependency tree
Reading state information... Done
python3 is already the newest version (3.7.3-1).

So that’s no help. Let’s google “install newer python on raspberry pi”. This leads me to a site that suggests I should build from source.

Here’s what that looked like:

$ wget https://www.python.org/ftp/python/3.11.4/Python-3.11.4.tgz
$ tar -zxvf Python-3.11.4.tgz
$ cd Python-3.11.4
$ ./configure
$ sudo make altinstall

This hit a snag. Because I have a dependency that’s from github directly, and not from PyPi, the python I build needs to be linked against openssl to download the dependency. It turns out that what ./configure is doing is inspecting the system and setting a bunch of build options. This configuration correctly detected that I didn’t have libssl-dev installed, meaning that when the python interpreter was being compiled, it didn’t have the opportunity to link against C code for making https connections, but I need those to install one of my dependencies. So I had to run sudo apt-get install libssl-dev, then run ./configure and ./sudo make altinstall again. Building Python on a Raspberry Pi takes forever, and now I’ve done it twice, so I think one lesson might be to pay attention to the output of ./configure and see whehter it’s compalining about missing libraries.

Anyway, now that I’ve built Python 3.11 on the Pi (twice!) I can go back to trying to install dependencies.

Step 2B: Keep installing dependencies

Now I can try python3.11 -m pip install ., which hits one more snag: it fails because there’s no README.md in my project. This seems really silly to me, but I added a README.md at the root of the project, ran the install command again, and now the dependencies are installed!

After that detour, I can go back to following pieces of the tutorial on this that I found.

Step 3: Configure Webserver

So now we’ve gotten our code and its dependencies onto the Pi. Now we need a process that will live on the Pi and serve requests. This kind of process is called a “server”. We’ll be using the apache2 webserver, which is a really common one.

Basically, the goal of that exercise is to write the XML config files for the apache2 webserver so that, when an http request comes in for the Pi, apache2 invokes our python code. The XML from the tutorial linked above doesn’t “just work,” so I need to dig in a bit into why it isn’t working. But I’ve never configured apach2 before. It seems like there are a bunch of XML files under /etc/apahc2 that need to agree on things like what files should be served and, if they’re interpreted files like python or php, how to invoke the interpreter. I think getting that set up correctly is a bit of a deeper dive, so I’ll work through it in the next post in the series.

Till then, happy learning!
– Will

Discussion

Love this post? Hate it? Is someone wrong on the internet? Is it me? Please feel free to @me on mastodon

I used to host comments on the blog, but have recently stopped. Previously posted comments will still appear, but for new ones please use the mastodon link above.

Join the conversation!