DEV Community

loading...
Cover image for Distribute a Python App via Bash Script

Distribute a Python App via Bash Script

Niklas Tiede
I'm a chemist who likes to experiment with code. 😉 ⚗️
Originally published at the-coding-lab.com ・3 min read

Heya fellows,

This is part 4 of the multi-part series "The Evolution of a Script". The code of this post can be found on Github (see here).

We created a useful tool, but wouldn't it be nice if we could make it accessible to others? So let's share it! At first, we have to make a snapshot of our virtual environment.

$ pip freeze > requirements.txt
Enter fullscreen mode Exit fullscreen mode

Thereafter we create a new Git repository and push it to Github!

$ echo "# tinyHTTPie" >> README.md
$ git init
$ git add .
$ git commit -m "first commit"
$ git branch -M main
$ git remote add origin https://github.com/NiklasTiede/tinyHTTPie.git
$ git push -u origin main
Enter fullscreen mode Exit fullscreen mode

Now others will be able to download our project using the clone command:

$ git clone https://github.com/NiklasTiede/tinyHTTPie.git
Enter fullscreen mode Exit fullscreen mode

Now they have to rebuild it by recreating the virtual environment, extracting the Python interpreter path, adding a shebang line to the script and an alias to .bashrc. Quite laborious. A bash script automates this process!

I store all my scripts within a MyScripts folder so the bash script will create it.

if [[ ! -d ~/MyScripts ]]; then
    mkdir ~/MyScripts
    folder1=~/MyScripts
    echo "${folder1} was generated."
fi
if [[ ! -d ~/MyScripts/tinyHTTPie ]]; then
    mkdir ~/MyScripts/tinyHTTPie
    folder2=~/MyScripts/tinyHTTPie
    echo "${folder2} was generated."
fi
Enter fullscreen mode Exit fullscreen mode

Then the tihttp.py and requirements.txt will be copied.

PWD=$(pwd)
REQUIREMENTS="$PWD/requirements.txt"
SCRIPT="$PWD/tihttp.py"
TARGET=~/MyScripts/tinyHTTPie

cp "$REQUIREMENTS" "$TARGET"
cp "$SCRIPT" "$TARGET"
cd ~/MyScripts/tinyhttp
Enter fullscreen mode Exit fullscreen mode

The Python interpreter version is checked.

PYVER=$(python --version)
CURRENT_PY_VERSION=${PYVER:7:11}
testvercomp ${CURRENT_PY_VERSION} 3.0.0 '>'
if [[ $(echo $CURRENT_PY_VERSION | grep '2.'*) ]]; then
    echo "first digit is 2, you're python version is too low"
elif [[ $(echo $CURRENT_PY_VERSION | grep '3.'*) ]]; then
    echo "first digit is 3, you're python versions fulfills the requirements!"
fi
Enter fullscreen mode Exit fullscreen mode

pipenv will be installed if it is not yet installed.

if [[ ! $(pipenv) ]]; then
    echo "pipenv not existent, so installing via pip..."
    pip install pipenv
    echo "...pipenv was installed?"
fi
Enter fullscreen mode Exit fullscreen mode

The virtual environment will be rebuilt.

pipenv install -r requirements.txt
Enter fullscreen mode Exit fullscreen mode

The shebang line is added.

pybin=$(pipenv --py)
echo -e "#\!${pybin}\n\n$(cat tinyhttp.py.py)" > tinyhttp.py
Enter fullscreen mode Exit fullscreen mode

The shebang is checked.

EXIS_HEADLINE=$(head -n 1 tinyhttp.py)
EXP_HEADLINE="#!${pybin}"
if [[ $EXIS_HEADLINE == $EXP_HEADLINE && ${#EXIS_HEADLINE} == ${#EXP_HEADLINE} ]]; then
    echo "shebang line was added correctly!"
elif [[ $EXIS_HEADLINE != $EXP_HEADLINE || ${#EXIS_HEADLINE} != ${#EXP_HEADLINE} ]]; then
    echo "shebang was NOT added correctly!"
fi
Enter fullscreen mode Exit fullscreen mode

File permissions are given.

chmod +x ~/MyScripts/tiniHTTP/tiny_HTTPie_clone.py
Enter fullscreen mode Exit fullscreen mode

The script adds the alias to the configuration file.

SHELL=$(printenv SHELL)
MYSHELL=${SHELL:5:10}
ALIASFILE=~/.bashrc

if [[ $MYSHELL  == "zsh" ]]; then
    echo "You're default shell is ZSH."
    if [[ -e ~/.aliases ]]; then
        ALIASFILE=~/.aliases
        echo "You're storing your files within the .aliases file."
    elif [[ -e ~/.zshrc ]]; then
        ALIASFILE=~/.zshrc
        echo "You're storing your files within the .zshrc file."
    fi
elif [[ $MYSHELL  == "bash" ]]; then
    echo "You're default shell is BASH."
    if [[ -e ~/.aliases ]]; then
        ALIASFILE=~/.aliases
        echo "You're storing your files within the .aliases file."
    elif [[ -e ~/.bashrc ]]; then
        ALIASFILE=~/.bashrc
        echo "You're storing your files within the .bashrc file."
    fi
fi
Enter fullscreen mode Exit fullscreen mode

And thats it! Puh, pretty much work and it's still pretty prone to errors (adding the script to the PATH instead of using an alias would make things less error prone). But there's a better solution to distribute packages in a standardized way: writing a setup.py file!

Discussion (0)