Once a year, I go and help with the technical infrastructure at a bird show. The program that they use to track the scores and classes of birds is quite old, does not scale well, and only supports Windows. I heard that Python is a great language to get something up and running quickly, which is why I chose it for this application, even though I know little about it. Learning a new language is fun, and I have been meaning to get into Python for a while.
Most tutorials you find on the internet start with "create a random python file and write some code". But this feels wrong for the people among us who have developed in other languages before. We started thinking about dependency management and how to share this properly with others that might work on this project. These are some of the questions that plagued my mind, prompted me to figure it out, and subsequently write this blog post.
There are several things that you need to successfully set up your Python project. You need to have a version of Python and pip installed on your computer. For the purposes of this blog, I'll assume that you already have these installed. A tool to write code is also handy. I use Visual Studio Code for this. I wrote this blog post while running Arch (btw), so it will be Linux and Bash flavored. Likewise, I cannot guarantee that the exact commands in this post will have the same result on a Windows or Mac machine.
Another thing we need to keep track of is code changes, versions, and shareability of our code. For this, I chose Git. This is important because I will be talking about the .gitignore file. In this file, we put a list of files that we want Git to ignore. Some files are meant to stay on our local computer only because they are generated locally. If someone checks out your code, they should generate these files for themselves. I am mostly talking about the dependencies here. This will become more concrete when we dive into the real setup.
Dependencies can be managed in two scopes, locally and globally. Locally is the best way to deal with dependencies of your project. Luckily, Python has a way to set up local dependencies that only affect our project.
We start with creating a directory for our project and running
git init
inside the newly created folder, this turns the folder into a git repository. We want to make sure our dependencies are set to be stored locally. To do this we run
python3 -m venv .venv
where the last parameter is the directory where you want to store your dependencies. I prefix it with a dot because that makes it a hidden folder within Linux. This folder should never be messed with manually and should only be manipulated by either Pip, python, or automatic actions of VS Code editor. Changing things manually will most likely cause breakage.
Creating a local environment for our Python dependencies does not automatically activate it, so we must do that ourselves. We do this by sourcing a file from our environment folder. Make sure your terminal is open in your project folder and run
source .venv/bin/activate
You will notice that your terminal line has changed slightly after running this command.
It now shows which environment you are working in. we can escape this environment by running the
deactivate
command. Note that closing your terminal also kicks you out of the local environment, this means that you must reactivate the environment whenever you open a new terminal window. Make sure that the environment is active when you want to run or test your Python project, or you'll get errors about missing dependencies!
Our local environment is ready to be used now that we have sourced it. Dependencies can now be installed with the pip command. Imagine that we want to use Flask to create a backend that can service some rest calls. Installing flask as a dependency would be done in the following way:
pip install flask
This will install the latest version of Flask in our local environment, ready to be used by our project.
It would be nice to be able to share our project now that we installed our dependencies and used them in our code to come to a working proof of concept. Remember that I turned our local environment into a hidden folder by prefixing it with a dot? What if I told you that we are not supposed to share this folder with others by checking it into git? That is right, others who want to work on our code must generate this folder and get the dependencies for themselves. Start by adding the environment to your `.gitignore` file so that git ignores the entire directory.
We will have to generate a list of our dependencies next, so that others know which dependencies, and versions, are needed to run our project. This can be done by running the command
pip freeze > requirements.txt
Opening the requirements.txt file will reveal a plain text list of dependencies with their version numbers. Run the command
pip install -r requirements.txt
to restore your local environment from this file. You can have as many of these files in your project as you want. This is a big bonus if you want to upgrade dependency versions. You have a dev list of up-to-date dependencies, and a production list with trustworthy good old versions. They can both be installed in the project at the same time. To switch between them, you must `source` the correct environment.
If you have followed along and created a local environment, a git repository and .gitignore file, then your project structure will now look something like this. You are now ready to start writing and sharing Python your code.
If you have questions, your own tips and tricks that result in better project scaffolding, or just want to discuss things, please do reach out to me on LinkedIn. Enjoy!