Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Documentation for #569 #574

Merged
merged 6 commits into from
Oct 4, 2018
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions docs/buildingpex.rst
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,14 @@ Even scripts defined by the "scripts" section of a distribution can be used, e.g
{bal,hit,hits,new,extend,expire,rm,as,approve,reject,unreject,bonus,notify,give-qual,revoke-qual}
...
mturk: error: too few arguments

Note: If you run ``pex -c`` and come across an error similar to
``pex.pex_builder.InvalidExecutableSpecification: Could not find script 'mainscript.py' in any distribution within PEX!``,
double-check your setup.py and ensure that ``mainscript.py`` is included
in your setup's ``scripts`` array. If you are using ``console_scripts`` and
run into this error, double check your ``console_scripts`` syntax - further
information for both ``scripts`` and ``console_scripts`` can be found in the
`Python packaging documentation <https://python-packaging.readthedocs.io/en/latest/command-line-scripts.html>`_.


Saving .pex files
Expand Down
1 change: 1 addition & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,5 @@ Guide:

whatispex
buildingpex
recipes
api/index
33 changes: 33 additions & 0 deletions docs/recipes.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
.. _recipes:

PEX Recipes and Notes
=====================

Gunicorn and PEX
----------------

Normally, to run a wsgi-compatible application with Gunicorn, you'd just
point Gunicorn at your application, tell Gunicorn how to run it, and you're
ready to go - but if your application is shipping as a PEX file, you'll have
to bundle Gunicorn as a dependency and set Gunicorn as your entry point. Gunicorn
can't enter a PEX file to retrieve the wsgi instance, but that doesn't prevent
the PEX from invoking Gunicorn.

This retains the benefit of zero `pip install`'s to run your service, but it
requires a bit more setup as you must ensure Gunicorn is packaged as a dependency.
The following snippets assume Flask as the wsgi framework, Django setup should be
similar:

.. code-block:: bash

$ pex flask gunicorn myapp -e gunicorn.app.wsgiapp -o ~/service.pex
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry about this - one last edit please: pex flask gunicorn myapp -c gunicorn -o ~/service.pex.

I do not know gunicorn and the -e seemed suspiciously manual for something that is presumably gunicorn bread and butter. My discovery process:

$ pex gunicorn -o gunicorn.pex
$ unzip -qc gunicorn.pex .deps/gunicorn-19.9.0-py2.py3-none-any.whl/gunicorn-19.9.0.dist-info/entry_points.txt

    [console_scripts]
    gunicorn=gunicorn.app.wsgiapp:run
    gunicorn_paster=gunicorn.app.pasterapp:run

    [paste.server_runner]
    main=gunicorn.app.pasterapp:paste_server
$ unzip -qc gunicorn.pex .deps/gunicorn-19.9.0-py2.py3-none-any.whl/gunicorn/app/wsgiapp.py | tail
    """\
    The ``gunicorn`` command line runner for launching Gunicorn with
    generic WSGI applications.
    """
    from gunicorn.app.wsgiapp import WSGIApplication
    WSGIApplication("%(prog)s [OPTIONS] [APP_MODULE]").run()


if __name__ == '__main__':
    run()

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh... I spent an embarrassing amount of time researching/asking questions regarding executing a specific module under gunicorn. And I'm glad it can be this simple. I hadn't seen a line of docs on entry_points until our chat here, even after digging deep into the python docs on setuputils. Now knowing about it, it's aggressively obvious in the Gunicorn setup file 🤕

This PR has been a journey of enlightenment.

So that totally works like a charm and simplifies a huge pile of assumptions I've had about the way I've been hot-wiring Gunicorn. Update commit inbound.


Once your pex file is created, you need to make sure to pass your wsgi app
instance name to the CLI at runtime for Gunicorn to know how to hook into it,
configuration can be passed in the same way:

.. code-block:: bash

$ service.pex myapp:appinstance -c /path/to/gunicorn_config.py

And there you have it, a fully portable python web service.