handling interpreters in *-snapper scripts (or snapcraft)

Barry Warsaw barry at ubuntu.com
Wed Jun 17 19:46:16 UTC 2015

Catching up on this thread...

On Jun 15, 2015, at 01:39 PM, Oliver Grawert wrote:

>the problem i am hitting my head against now is how to handle these
>hardcoded interpreter lines without requiring the user to manually
>re-write them when producing a snap (or have error prone code in the
>*-snapper script to mangle them with a prefix or some such)

Note that the standard Debian build tools already rewrite the shebang lines
for Python scripts:

From dh_python3(1):

              do not rewrite shebangs

              use given command as shebang in scripts

              do not translate shebangs into Debian dependencies

If you use console_scripts in entry_points (which I recommend), then
setuptools will create the shebang for you when it creates the script.


On Jun 15, 2015, at 07:55 AM, Rick Spencer wrote:

>How does one manage porting a Python app to different platforms today?
>Surely /bin/... is not functional on Macs and Windows?

/usr/bin sure is for Mac.  Who knows about Windows? :)

On Jun 15, 2015, at 02:00 PM, Alexander Sack wrote:

>maybe #!/usr/bin/env python and then make snappy hook into that env to adjust
>the PATH to look at right place inside the snap that gets launched?

Generally it's not a good idea to use /usr/bin/env to find the right Python
for built-and-deployed scripts because you don't want someone's crazy $PATH
breaking the system script.  It's fine (and recommended) for upstream source
dev branches because then it's easier to test against multiple Pythons,
although with tools like tox, I think even that recommendation may be

In the snappy case, /usr/bin/env isn't a terrible option because it's highly
unlikely that there will be any other Python on the $PATH.

Remember too that shebangs are just suggestions <wink>!  You can always
override them by explicitly executing the script with the given hardcoded
interpreter path.  So if you really wanted to run e.g. /usr/bin/virtualenv
with Python 2, you just do it like so:

$ /usr/bin/python2 /usr/bin/virtualenv ...

So it may make sense for the snappy build process to just write a wrapper that
does the actual executing of the script even without fiddling with the $PATH
or adjusting shebangs.

On Jun 15, 2015, at 02:57 PM, Didier Roche wrote:

>However, I can clearly see some apps doing some kind of:
>subprocess.call(["/usr/bin/python", "foo"])
>Should we care of those use cases? That's the real question I guess…

Gosh, I really hope no code is doing that!  If it is, it's a bug.

If you want to run a subprocess with the same interpreter that the parent is
running, use sys.executable to calculate that dynamically.  If you needed to
run a different interpreter (e.g. the parent is Python 3 but for some reason
the child is limited to Python 2), then path manipulation of sys.executable is
probably the safest.

Another thought about virtual environments: we're strongly encouraging Python
3, in which case you should be using the built-in pyvenv command (although
under Debuntu that comes in a separate binary package).  Sure, we shouldn't
prohibit snaps in Python 2 if that's what the snapper wants, but the
opinionated path should use pyvenv instead virtualenv.


More information about the snappy-devel mailing list