|
# Adding Abseil (absl) flags quickstart |
|
## Defining a flag |
|
absl flag definitions are similar to argparse, although they are defined on a global namespace. |
|
|
|
For instance defining a string flag looks like: |
|
```$xslt |
|
from absl import flags |
|
flags.DEFINE_string( |
|
name="my_flag", |
|
default="a_sensible_default", |
|
help="Here is what this flag does." |
|
) |
|
``` |
|
|
|
All three arguments are required, but default may be `None`. A common optional argument is |
|
short_name for defining abreviations. Certain `DEFINE_*` methods will have other required arguments. |
|
For instance `DEFINE_enum` requires the `enum_values` argument to be specified. |
|
|
|
## Key Flags |
|
absl has the concept of a key flag. Any flag defined in `__main__` is considered a key flag by |
|
default. Key flags are displayed in `--help`, others only appear in `--helpfull`. In order to |
|
handle key flags that are defined outside the module in question, absl provides the |
|
`flags.adopt_module_key_flags()` method. This adds the key flags of a different module to one's own |
|
key flags. For example: |
|
```$xslt |
|
File: flag_source.py |
|
--------------------------------------- |
|
|
|
from absl import flags |
|
flags.DEFINE_string(name="my_flag", default="abc", help="a flag.") |
|
``` |
|
|
|
```$xslt |
|
File: my_module.py |
|
--------------------------------------- |
|
|
|
from absl import app as absl_app |
|
from absl import flags |
|
|
|
import flag_source |
|
|
|
flags.adopt_module_key_flags(flag_source) |
|
|
|
def main(_): |
|
pass |
|
|
|
absl_app.run(main, [__file__, "-h"] |
|
``` |
|
|
|
when `my_module.py` is run it will show the help text for `my_flag`. Because not all flags defined |
|
in a file are equally important, `official/utils/flags/core.py` (generally imported as flags_core) |
|
provides an abstraction for handling key flag declaration in an easy way through the |
|
`register_key_flags_in_core()` function, which allows a module to make a single |
|
`adopt_key_flags(flags_core)` call when using the util flag declaration functions. |
|
|
|
## Validators |
|
Often the constraints on a flag are complicated. absl provides the validator decorator to allow |
|
one to mark a function as a flag validation function. Suppose we want users to provide a flag |
|
which is a palindrome. |
|
|
|
```$xslt |
|
from absl import flags |
|
|
|
flags.DEFINE_string(name="pal_flag", short_name="pf", default="", help="Give me a palindrome") |
|
|
|
@flags.validator("pal_flag") |
|
def _check_pal(provided_pal_flag): |
|
return provided_pal_flag == provided_pal_flag[::-1] |
|
|
|
``` |
|
|
|
Validators take the form that returning True (truthy) passes, and all others |
|
(False, None, exception) fail. |
|
|
|
## Testing |
|
To test using absl, simply declare flags in the setupClass method of TensorFlow's TestCase. |
|
|
|
```$xslt |
|
from absl import flags |
|
import tensorflow as tf |
|
|
|
def define_flags(): |
|
flags.DEFINE_string(name="test_flag", default="abc", help="an example flag") |
|
|
|
|
|
class BaseTester(unittest.TestCase): |
|
|
|
@classmethod |
|
def setUpClass(cls): |
|
super(BaseTester, cls).setUpClass() |
|
define_flags() |
|
|
|
def test_trivial(self): |
|
flags_core.parse_flags([__file__, "test_flag", "def"]) |
|
self.AssertEqual(flags.FLAGS.test_flag, "def") |
|
|
|
``` |
|
|