This brief article discusses some issues we have had with Python packages on data center servers where we can't become root and needed to navigate various site customizations. For certain Python packages, we want to work with the Git repo so we have access to the latest release, experimental branches, and have an ability to apply various patches with ease.
An example of this is the Django web framework. When we set up our web project on a particular data center Linux machine and configured it for Django, we found that the provider installed a Python package in a library path picked up during initialization (and added to sys.path).
If you're not familiar with sys.path, it is a Python list of strings that specifies the search path for modules.
Although you can find your site package directories through site.getsitepackages() and site.getusersitepackages(), additional paths may be added by the sitecustomize module, which are imported during initialization. The Python site documentation states the module "can perform arbitrary site-specific customizations", and we have found this to be the case.
One useful option when experimenting with the interaction of the site module and related path manipulations is to invoke python with the "-S" option. From the python docs: "Disable the import of the module site and the site-dependent manipulations of sys.path that it entails. Also disable these manipulations if site is explicitly imported later."
One brute force option we have when using a clone of a Git repo is to manually add it to our path using sys and this also provides an opportunity to show the use of "-S", as shown below:
$ python3 -S Python 3.13.7 (main, Aug 15 2025, 23:01:14) >>> import sys >>> import django ... ModuleNotFoundError: No module named 'django' >>> sys.path.append(<local path to django>) >>> import django >>> django.VERSION (5, 2, 6, 'final', 0)
So assuming you have a handle on where your modules are being found and imported, let's turn to the simple task of working with a cloned Git repo instead of an installed Python package, as shown below:
$ cd /build # this is where we clone our repos $ git clone https://github.com/django/django.git Cloning into 'django'... $ cd django $ git checkout 5.2.6
Next cd to the path where your account's modules are imported (site.getusersitepackages()) and create a django.pth file. In the file, add the path to where you cloned the Django repo.
The django.pth file will direct Python to add the repo to sys.path during site initialization so it can be found during an import.
>> import django >> django.__file__ '/build/django/django/__init__.py'
Now that you are working from a git repo in the cloud for your Python package, you can easily update / patch it, try different branches from the remote origin, and create your own branches for experiments.
However, when updating a Python repo, we have found the need to clear the __pycache__ folders since the ".pyc" files may be stale and cause issues. For Django with Apache, we have found errors like the following after a repo update and restart:
ImportError: bad magic number in 'django.contrib.sitemaps.models': b'\\x03\\xf3\\r\\n'We resolve it by doing the following to clear out __pycache__:
$ cd /build/django # location of our Django Git repo $ find . -name '*.pyc' | xargs rm $ find . -name '*.pyc' $ # they're all gone
References
- Python site: Site-specific configuration hook
- Python sys: System-specific parameters and functions




