1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
|
.. _qtut_ini:
=================================================
03: Application Configuration with ``.ini`` Files
=================================================
Use Pyramid's ``pserve`` command with a ``.ini`` configuration file for
simpler, better application running.
Background
==========
Pyramid has a first-class concept of
:ref:`configuration <configuration_narr>` distinct from code.
This approach is optional, but its presence makes it distinct from
other Python web frameworks. It taps into Python's ``setuptools``
library, which establishes conventions for installing and providing
"entry points" for Python projects. Pyramid uses an entry point to
let a Pyramid application know where to find the WSGI app.
Objectives
==========
- Modify our ``setup.py`` to have an entry point telling Pyramid the
location of the WSGI app
- Create an application driven by a ``.ini`` file
- Startup the application with Pyramid's ``pserve`` command
- Move code into the package's ``__init__.py``
Steps
=====
#. First we copy the results of the previous step:
.. code-block:: bash
$ cd ..; cp -r package ini; cd ini
#. Our ``ini/setup.py`` needs a setuptools "entry point" in the
``setup()`` function:
.. literalinclude:: ini/setup.py
:linenos:
#. We can now install our project, thus generating (or re-generating) an
"egg" at ``ini/tutorial.egg-info``:
.. code-block:: bash
$ $VENV/bin/python setup.py develop
#. Let's make a file ``ini/development.ini`` for our configuration:
.. literalinclude:: ini/development.ini
:language: ini
:linenos:
#. We can refactor our startup code from the previous step's ``app.py``
into ``ini/tutorial/__init__.py``:
.. literalinclude:: ini/tutorial/__init__.py
:linenos:
#. Now that ``ini/tutorial/app.py`` isn't used, let's remove it:
.. code-block:: bash
$ rm tutorial/app.py
#. Run your Pyramid application with:
.. code-block:: bash
$ $VENV/bin/pserve development.ini --reload
#. Open http://localhost:6543/.
Analysis
========
Our ``development.ini`` file is read by ``pserve`` and serves to
bootstrap our application. Processing then proceeds as described in
the Pyramid chapter on
:ref:`application startup <startup_chapter>`:
- ``pserve`` looks for ``[app:main]`` and finds ``use = egg:tutorial``
- The projects's ``setup.py`` has defined an "entry point" (lines 9-12)
for the project "main" entry point of ``tutorial:main``
- The ``tutorial`` package's ``__init__`` has a ``main`` function
- This function is invoked, with the values from certain ``.ini``
sections passed in
The ``.ini`` file is also used for two other functions:
- *Configuring the WSGI server*. ``[server:main]`` wires up the choice of
which WSGI *server* for your WSGI *application*. In this case, we are using
``wsgiref`` bundled in the Python library. It also wires up the *port
number*: ``port = 6543`` tells ``wsgiref`` to listen on port 6543.
- *Configuring Python logging*. Pyramid uses Python standard logging, which
needs a number of configuration values. The ``.ini`` serves this function.
This provides the console log output that you see on startup and each
request.
We moved our startup code from ``app.py`` to the package's
``tutorial/__init__.py``. This isn't necessary,
but it is a common style in Pyramid to take the WSGI app bootstrapping
out of your module's code and put it in the package's ``__init__.py``.
The ``pserve`` application runner has a number of command-line arguments
and options. We are using ``--reload`` which tells ``pserve`` to watch
the filesystem for changes to relevant code (Python files, the INI file,
etc.) and, when something changes, restart the application. Very handy
during development.
Extra Credit
============
#. If you don't like configuration and/or ``.ini`` files,
could you do this yourself in Python code?
#. Can we have multiple ``.ini`` configuration files for a project? Why
might you want to do that?
#. The entry point in ``setup.py`` didn't mention ``__init__.py`` when
it declared ``tutorial:main`` function. Why not?
#. What is the purpose of ``**settings``? What does the ``**`` signify?
.. seealso::
:ref:`project_narr`,
:ref:`scaffolding_chapter`,
:ref:`what_is_this_pserve_thing`,
:ref:`environment_chapter`,
:ref:`paste_chapter`
|