[egenix-users] single file executables with pyrun (and a little help from makeself)

M.-A. Lemburg mal at egenix.com
Wed Jun 5 21:05:16 CEST 2019


Hi Holger,

glad you like PyRun :-)

On 29.05.2019 14:00, Holger Joukl wrote:
> 
> Hi,
> 
> I'm currently beginning to think pyrun is one of the best things since
> sliced bread ;-)
> 
> Of course users on this list have probably known that for years (I first
> learned
> about pyrun at PyCon.DE 2013 (I think) and have gotten round to actually
> trying
> it just now. Can you believe that.)
> 
> Sample usecase: A simple sane webdav client using easywebdav as a small,
> single file
> Python script (right now not a "proper" Python package at all, i.e. no
> setup.py and
> module structure and whatnot).
> 
> Run from a virtualenv but alas I now want to use this somewhere else:
> A machine where not even said virtualenv's base interpreter is available.
> Think an old RHEL box where it's not even Python 2.7-time yet (not even
> that exotic
> in the enterprisey world).
> 
> So, for future reference:
> 
> Enter pyrun:
> 
> # Prerequisites:
> # Download install-pyrun
> # Download makeself: https://github.com/megastep/makeself (nice!)
> 
> # Opionally, set your env intricacies e.g.
> #
> # export PROXY=...      # in case you need a https proxy
> # export CA_BUNDLE=...  # in case you need to provide a custom ssl
> certififates bundle to avoid ssl errors
> # export LIBPATH=...    # in case some mandatory libs are not installed in
> system search paths
> #
> # (I'm leaving all this in for documentational purposes)
> 
> # install pyrun and create "pyrun-venv" named webdav
> # (add --log to make this write <venv-name>/pyrun-installation.log)
> (LD_LIBRARY_PATH=$LIBPATH CURL_CA_BUNDLE=$CA_BUNDLE ./install-pyrun --debug
> --setuptools-version=latest --pip-version=latest --python-unicode=ucs4
> webdav)
> 
> # copy some mandatory library dependencies to the pyrun-venv to make it
> self-sufficient
> # (these are not globally available on our target machines and/or installed
> # at our non-standard location LIBPATH)
> cp $LIBPATH/libcrypto.so.1.0.0 $LIBPATH/libssl.so.1.0.0 ./webdav/lib/
> 
> # These next 2 steps would be replaced by installing my script's proper
> python package
> # and its requirements, if I had set this up
> # install the python dependencies for my script
> ./webdav/bin/pip install --proxy "$PROXY" --cert "$CA_BUNDLE" --timeout=120
> -r packages.txt
> # copy my script to the pyrun-venv
> cp ~/pydev/tools/bin/webdav webdav/bin/
> 
> # modify shebang line to enable relative pyrun python interpreter
> sed -i 's%#!.*python.*%#!/usr/bin/awk BEGIN{a=ARGV[1];b="";for(i=1;i<ARGC;i
> ++){b=b"\\t"ARGV[i];}sub(/[a-z_.\\-]+$/,"python",a);rc=system(a""b);exit
> rc}%g' webdav/bin/webdav
> 
> # extract makeself to use it
> ./makeself-2.4.0.run
> 
> # create a single file executable from the script with makeself
> # (i.e. a self extracting archive that runs the included script)
> ./makeself-2.4.0/makeself.sh webdav webdav.run "webdav command line
> client" ./bin/webdav
> 
> # run our executable
> ./webdav.run -- -h    # makeself treats options after -- as options for the
> script to run
> 
> # we now have a fully *relocatable* single file executable, bundling the
> *complete pyrun interpreter*
> # *plus* our script with all its Python dependencies *and* some shared
> libraries (!):
> du -ms ./webdav.run
> 19	./webdav.run

Nice, I didn't know about makeself before.

> Some notes:
> - makeself adds stdout output when running the executable that I haven't
> been
> able to suppress, like
> Verifying archive integrity...  100%   All good.
> Uncompressing webdav command line client  100%
> 
> - makeself adds its own options list to the command line so options to the
> target script must come after --
> 
> - makeself extracts to a temporary directory and changes into that
> directory
> before running the target script. Of course, this doesn't play well with
> e.g. relative
> path arguments to a script. To care for this, makeself provides the env
> variable USER_PWD
> to the invoked target script, containing the current working dir before the
> "cd $TMPDIR".
> USER_PWD can then be respected by the script. Of course the script must
> then be
> "makeself-instrumented", which is subpar somehow.
> 
> All of these could be addressed in a custom makeself-like self-extractor or
> maybe added as optional makeself features.
> 
> - Is there a nicer way to provide for the relative pyrun interpreter path
> in the script shebang?
> 
> This is really quite powerful - deployment is now moving around a
> relocatable
> "binary", much like go :-)

It'll get even better:

With the next release, we'll officially support adding ZIP files
to the PyRun executable.

This means that you can do things like these:

- create a Python app dir with some Python modules:
  a.py
  b.py

- add a __main__ to the top-level:
  __main__.py
  (with code to start the app using the other two modules)

- ZIP all files:
  zip myapp.zip a.py b.py __main__.py

- "build" your one file app:
  cat pyrun myapp.zip > myapp
  chmod 755 myapp

- run your app:
  ./myapp

PyRun will check for a ZIP file add-on in case it finds that
the binary does not start with "pyrun" or "python".

Cheers,
-- 
Marc-Andre Lemburg
eGenix.com

Professional Python Services directly from the Experts (#1, Jun 05 2019)
>>> Python Projects, Coaching and Consulting ...  http://www.egenix.com/
>>> Python Database Interfaces ...           http://products.egenix.com/
>>> Plone/Zope Database Interfaces ...           http://zope.egenix.com/
________________________________________________________________________

::: We implement business ideas - efficiently in both time and costs :::

   eGenix.com Software, Skills and Services GmbH  Pastor-Loeh-Str.48
    D-40764 Langenfeld, Germany. CEO Dipl.-Math. Marc-Andre Lemburg
           Registered at Amtsgericht Duesseldorf: HRB 46611
               http://www.egenix.com/company/contact/
                      http://www.malemburg.com/



More information about the egenix-users mailing list