With the news about MS Paint going away from the default MS install, it might be timely to look at other ways to edit images. The most common edit I need to do is to crop images -- and this is what we will use as an example.

My favorite image editing tool is Jupyter. Jupyter needs some encouragement to be an image editor -- and to easily open images. As is often the case, I have a non-pedagogical, but useful, preamble. The preamble turns Jupyter into an image editor.

from matplotlib.pyplot import imshow
import numpy
import PIL
import os

%matplotlib inline

def inline(some_image):

def open(file_name):
    return PIL.Image.open(os.path.expanduser(file_name))

With the boring part done, it is time to edit some images! In the Shopkick birthday party, I had my caricature drawn. I love it -- but it has a whole baggage talking about the birthday party which is irrelevant for uploading to Facebook.

I have downloaded the image from the blog. I use Pillow (the packaging fork of PIL) to open the image.


Then I want to visually inspect the image inline:


I use the crop method, and directly inline it:


If this was longer, and more realistic, this would be playing with the numbers back and forth -- and maybe resize, or combine it with other images.

The Pillow library is great, and this way we can inspect the results as we are modifying the image, allowing iterative image editing. For people like me, without a strong steady artist's hand to perfectly select the right circle, this solution works just great!

Anatomy of a Multi-Stage Docker Build

Wed 19 July 2017 by Moshe Zadka

Docker, in recent versions, has introduced multi-stage build. This allows separating the build environment from the runtime envrionment much more easily than before.

In order to demonstrate this, we will write a minimal Flask app and run it with Twisted using its WSGI support.

The Flask application itself is the …

read more

Bash is Unmaintainable Python

Mon 17 July 2017 by Moshe Zadka

(Thanks to Aahz, Roy Williams, Yarko Tymciurak, and Naomi Ceder for feedback. Any mistakes that remain are mine alone.)

In the post about building Docker applications, I had the following Python script:

import datetime, subprocess
tag = datetime.datetime.utcnow().isoformat()
tag = tag.replace(':', '-').replace('.', '-')
for ext in ['', '-slim']:
    image = "moshez …
read more

Imports at a Distance

Sun 25 June 2017 by Moshe Zadka

(Thanks to Mark Williams for feedback and research)

Imagine the following code:

## mymodule.py
import toplevel.nextlevel.lowmodule

def _func():

def main():

Assuming the toplevel.nextlevel.module does define a function dosomething, this code seems to work just fine.

However, imagine that later we …

read more

X Why Zip

Sat 24 June 2017 by Moshe Zadka

PEP 441 resulted in the creation of the zipapp module. The PEP says "Python has had the ability to execute directories or ZIP-format archives as scripts since version 2.6 [...] This feature is not as popular as it should be mainly because it was not promoted as part of Python …

read more

Nitpicks are for Robots

Fri 09 June 2017 by Moshe Zadka

Many projects and organizations have a coding standard. For Python, much of the time, the standard is a variant of PEP 8. During code reviews, often the reviewer will point out where the code disagrees with the standard, and ask for it to be fixed. Sometimes, if the reviewer is …

read more

My Little Subclass: Inheritance is Magic

Sat 29 April 2017 by Moshe Zadka

Learning about Python Method Resolution Order with Twilight Sparkle and her friends.

(Thanks to Ashwini Oruganti for her helpful suggestions.)

The show "My Little Pony: Friendship is Magic" is the latest reimagination of the "My Little Pony" brand as a TV show. The show takes place, mostly, in Ponyville and …

read more

PYTHONPATH Considered Harmful

Tue 11 April 2017 by Moshe Zadka

(Thanks to Tim D. Smith and Augie Fackler for reviewing a draft. Any mistakes that remain are mine.)

The environment variable PYTHONPATH seems harmless enough. The official documentation refers to its function as "Augment the default search path for module files." However, in practice, setting this variable in a shell …

read more

Shipping Python Applications in Docker

Fri 17 March 2017 by Moshe Zadka


When looking in open source examples, or tutorials, one will often see Dockerfiles that look like this:

FROM python:3.6
COPY setup.py /mypackage
COPY src /mypackage/src
COPY requirements.txt /
RUN pip install -r /requirements.txt
RUN pip install /mypackage
ENTRYPOINT ["/usr/bin/mypackage-console-script", "some", "arguments"]

This …

read more

Pelican -- an Experiment

Tue 07 March 2017 by Moshe Zadka

An experimental blog

read more