Tip
Hover your cursor over any code block in this tutorial, and a clipboard will appear. Click it to copy the contents of the code block.
Prerequisites
This tutorial assumes that you have completed the earlier tutorial: Create and Launch a Basic Application with Hydra
Add a Command Line Interface to Our Application#
In this tutorial we will update our project so that it can be configured and launched from a command line interface (CLI), using Hydra.
In the last section of the tutorial, we
Defined a task function
Created a config for that task function
Ran the task function via
hydra_zen.launch(Config, task_function, overrides=<...>)
In this section, we need to add our config to Hydra’s config-store; this enables Hydra to generate a CLI from this config.
Modifying Our Project#
Open my_app.py
in your editor. We will make the following modifications to it:
Use
hydra_zen.ZenStore
to store our config locally.Add a
__main__
clause to ourmy_app.py
script so that the script runs our task function.Within
__main__
populate Hydra’s global config store so that Hydra can generate a CLI using our configs.Use
hydra_zen.zen()
to wrap the task function and to generate the CLI.
Modify your script to match this:
from hydra_zen import builds, zen, ZenStore
# The same task function as before
def task_function(player1: str, player2: str):
with open("player_log.txt", "w") as f:
f.write("Game session log:\n")
f.write(f"Player 1: {player1}\n" f"Player 2: {player2}")
return player1, player2
Config = builds(task_function, populate_full_signature=True)
# 1) Create a local config store and store our config
store = ZenStore()
store(Config, name="my_app")
# 2) Adding our __main__ clause to our script.
# Executing `python my_app.py [...]` will generate a CLI for our running
# our task function
if __name__ == "__main__":
# 3) We need to add the configs from our local store to Hydra's
# global config store
store.add_to_hydra_store()
# 4) hydra_main generates a CLI based off of the config
# stored under the name "my_app", and will run
# `task_function`
zen(task_function).hydra_main(config_name="my_app",
version_base="1.1",
config_path=None,
)
Launching Our Application from the Command Line#
With the above modifications to my_app.py
complete, we can launch our application
from the command line. The following will launch a job with mario
and luigi
as
the names for player 1 and player 2, respectively.
Open your terminal in the same directory as my_app.py
.
We can view the configurable aspects of our application using the --help
command; run the following:
$ python my_app.py --help
my_app is powered by Hydra.
== Configuration groups ==
Compose your configuration from those groups (group=option)
== Config ==
Override anything in the config (foo.bar=value)
player1: ???
player2: ???
See that our app requires that we configure two fields: player1
and player2
.
Let’s configure these fields with the string values "mario"
and "luigi"
, respectively.
In your console execute the following command:
$ python my_app.py player1=mario player2=luigi
Tip
You can add tab-completion to your application’s command line interface. This is helpful once you start writing applications that have many configurable components.
To inspect the log written by our application, open a Python terminal in the same
directory as my_app.py
and define the following function for reading files
Getting the directory containing the output of this job:
>>> *_, latest_job = sorted((Path.cwd() / "outputs").glob("*/*"))
>>> latest_job # changes based on reader's date, time, and OS
WindowsPath('C:/outputs/2021-10-21/12-58-13')
Print the contents of player_log.txt
and verify that it matches with how we ran our
program:
>>> print_file(latest_job / "player_log.txt")
Game session log:
Player 1: mario
Player 2: luigi
Voilà! As demonstrated, our simple application can now be configured and launched from the
command line. It should be noted that we can still launch our app from a Python
console, using launch()
, as we did in the previous tutorial.
Streamlining Our Code#
hydra_zen.ZenStore
has auto-config capabilities and it
can be used as a decorator. This enables us to both create and store a config for our task function in a single line.
from hydra_zen import zen, ZenStore
store = ZenStore()
@store(name="my_app")
def task_function(player1: str, player2: str):
with open("player_log.txt", "w") as f:
f.write("Game session log:\n")
f.write(f"Player 1: {player1}\n" f"Player 2: {player2}")
return player1, player2
if __name__ == "__main__":
store.add_to_hydra_store()
zen(task_function).hydra_main(config_name="my_app",
version_base="1.1",
config_path=None,
)
Here, applying @store("my_app")
to task_function
is equivalent to
store(builds(task_function, populate_full_signature=True), name="my_app")
Reference Documentation#
Want a deeper understanding of how hydra-zen and Hydra work? The following reference materials are especially relevant to this tutorial section.
Attention
Cleaning Up:
To clean up after this tutorial, delete the outputs
directory that Hydra created
upon launching our application.