cat /dev/brain |

Don't use setuptools entry points…

published on Saturday, February 25, 2017

…for small scripts.

Update: I realized that pip install doesn't have the problem described here. This means that you can safely use entry points without any patches if you recommend that users install with pip. For more information, see the post 4 reasons to always use pip for installation.

Setuptools provides a feature called entry points that can be used to define for which functions the setup script should create executables – or to register plugins. This is pretty cool (and even works on windows)!

The downside is that entry points have insanely bad startup times: A simple hello-world program invoked through an entry point takes an embarrassing 0.2 seconds (!!!) to run on my system – and even much longer (about 2-5 seconds) if loaded for the first time.

Is this overhead due to loading the python environment itself? Let's have a look. An executable for an entry point generated by setuptools generally does something like this:

from pkg_resources import load_entry_point
load_entry_point('hello_world', 'console_scripts', 'hello-world')()

The same application runs almost instantaneously, if we replace this as follows:

import hello_world
hello_world.main()

In fact, the main cost is from importing pkg_resources. Try it yourself:

% time python -c 'import pkg_resources'
python -c 'import pkg_resources'  0.19s user 0.02s system 99% cpu 0.215 total

% time python -c 'import hello_world'
python -c 'import hello_world'  0.02s user 0.00s system 92% cpu 0.025 total

The issue is known but I'm not sure anyone is going to fix it anytime soon.

So what to do about it? For now I'm using fast-entry_points which patches the setuptools script generator with a replacement as shown above.

Spread the word!

This entry was tagged bug, deployment, performance, python, rant and setuptools