• +43 660 1453541
  • contact@germaniumhq.com

Creating Replacement Shell Scripts in Python II


Creating Replacement Shell Scripts in Python II

So in the yesterday’s article I ranted on why shell scripting in general, with bash in particular is terrible. But there’s a reason why we write shell scripts, namely that we’re in the same domain of the commands that we know. Here’s how to use the same knowledge in the python scripts:

Use the subprocess module. This allows us the ability to call programs, and wait for their termination, with control on errors, and output capturing. For example let’s assume we want to call git cherry-pick something, and we want to execute the command, and see when it fails:

subprocess.check_call(["git", "cherry-pick", "backport_%s_to_%s" %
    (normalize_issue_name(issue_id), to_version)])

We have now full control on parameters, we have the option of parsing the parameters using an easy to follow syntax. For example that’s how we extract the name of the current branch using just the shell commands into our script:

def get_checked_out_branch_name() -> str:
    return subprocess.check_output(["git", "rev-parse", "--abbrev-ref", "HEAD"]) \
                     .strip() \
                     .decode('utf-8')

For the moving/copying files around, the shutil module is there to provide us a bunch of copying, moving or removing operations with files.

The last operation that I can think of is the recursive search. But even there a simple os.walk() does it. Note that in this approach nothing stops us to still use the find command if we really want to, by simply calling the subprocess.check_output(['find', '…​'), and then simply iterating over the lines.

But now we can use modules, the type system from Python 3.5+, and all the other extra modules, and the script notation is actually understandable and maintainable.

And that’s what makes it awesome.