Dealing With Pyc Files When Working With Git.
Python developers are familiar with the fact that Python automatically generates a byte code from the .py
file, which is executed by the interpreter. This byte code is stored in a .pyc
file, usually in the same directory of its respective source file. The .pyc
generation can happen either when the main Python script is being executed or when a module is imported for the first time.
As an example, in many Python web frameworks when we create a views.py
, a file containing the logic for our views, we will most probably get a views.pyc
file in the same directory after running an instance of our application.
As developers, we often work with big codebases utilizing Git, and on projects with many developers in teams. This means a bunch of features are being developed at the same time, and thus we have to switch branches frequently to pair with other developers, or to review and test someone’s code. Depending on the differences between two branches, we can end up with .pyc
files from the other branch, which can lead to unexpected behaviors.
Git is a well known source code management tool which cleverly provides hooks, a way to fire custom scripts when certain important actions occur. We can include hooks to the most used actions, like before or after committing, pushing, rebasing, merging, and similar.
One of the available hooks is a “post-checkout” hook, which is fired after we checkout another branch or specific commit. We can include our code to clean the .pyc
files in the “post-checkout” hook. All Git projects have .git
folder in the project’s root and from there we just need to edit (or create new) file .git/hooks/post-checkout
, by adding the following code:
#!/bin/sh
find . -type f -name "*.py[co]" -delete
find . -type d -name "__pycache__" -delete
This is for Linux and Mac. On Windows, first we need to install Cygwin, so Git can execute the hook scripts as shell. Then we need to change the commands a little bit:
#!/bin/sh
find . -type f -name "*.py[co]" | xargs rm
find . -type d -name "__pycache__" | xargs rm -rf
When the Python interpreter is invoked with the -O
flag, optimized code is generated and stored in .pyo
files. For that reason, our command checks for .pyc
or .pyo
files and removes them (*.py[co]
). Python 3 stores its compiled bytecode in __pycache__
directories, so we included a command that will remove them as well.
In the end, after saving our hook file on Linux and Mac, we need to make sure we add execution permissions to it:
$ chmod +x .git/hooks/post-checkout
Contributors
Ivan Neto
Ivan is an engineer with eight years of experience in software and web development. Primarily focused on the web, he has solved code optimization problems arising from growing systems, as well as the migrated production apps and services on-the-fly with zero downtime. While a major part of his experience has been on the back-end, he can also work with the front-end, databases, networking, and infrastructure.
Show More