Fabfile construction and use¶
This document contains miscellaneous sections about fabfiles, both how to best write them, and how to use them once written.
Fabfile discovery¶
Fabric is capable of loading Python modules (e.g. fabfile.py
) or packages
(e.g. a fabfile/
directory containing an __init__.py
). By default, it
looks for something named (to Python’s import machinery) fabfile
- so
either fabfile/
or fabfile.py
.
The fabfile discovery algorithm searches in the invoking user’s current working
directory or any parent directories. Thus, it is oriented around “project” use,
where one keeps e.g. a fabfile.py
at the root of a source code tree. Such a
fabfile will then be discovered no matter where in the tree the user invokes
fab
.
The specific name to be searched for may be overridden on the command-line with
the -f
option, or by adding a fabricrc line which
sets the value of fabfile
. For example, if you wanted to name your fabfile
fab_tasks.py
, you could create such a file and then call fab -f
fab_tasks.py <task name>
, or add fabfile = fab_tasks.py
to
~/.fabricrc
.
If the given fabfile name contains path elements other than a filename (e.g.
../fabfile.py
or /dir1/dir2/custom_fabfile
) it will be treated as a
file path and directly checked for existence without any sort of searching.
When in this mode, tilde-expansion will be applied, so one may refer to e.g.
~/personal_fabfile.py
.
Note
Fabric does a normal import
(actually importlib.import_module()
) of your
fabfile in order to access its contents – it does not do any eval
-ing
or similar. In order for this to work, Fabric temporarily adds the found
fabfile’s containing folder to the Python load path (and removes it
immediately afterwards.)
Importing Fabric¶
Because Fabric is just Python, you can import its components any way you
want. However, for the purposes of encapsulation and convenience (and to make
life easier for Fabric’s packaging script) Fabric’s public API is maintained in
the fabric.api
module.
All of Fabric’s Operations, Context Managers, Decorators and Utils are included in this module as a single, flat namespace. This enables a very simple and consistent interface to Fabric within your fabfiles:
from fabric.api import *
# call run(), sudo(), etc etc
This is not technically best practices (for a
number of reasons) and if you’re only using a couple of
Fab API calls, it is probably a good idea to explicitly from fabric.api
import env, run
or similar. However, in most nontrivial fabfiles, you’ll be
using all or most of the API, and the star import:
from fabric.api import *
will be a lot easier to write and read than:
from fabric.api import abort, cd, env, get, hide, hosts, local, prompt, \
put, require, roles, run, runs_once, settings, show, sudo, warn
so in this case we feel pragmatism overrides best practices.
Defining tasks and importing callables¶
For important information on what exactly Fabric will consider as a task when it loads your fabfile, as well as notes on how best to import other code, please see Defining tasks in the Execution model documentation.