Storing the configuration in PY files

The PY file format means using Python code as the configuration file. This pairs nicely with the use of the same language implementing the application. We will have a configuration file that's simply a module; the configuration is written in the Python syntax. This can remove the need for sophisticated parsing to get the configuration values.

Using Python gives us a number of design considerations. We have two overall strategies to use Python as the configuration file:

  • A top-level script: In this case, the configuration file is simply the top-most main program.
  • An exec() import: In this case, our configuration file provides parameter values that are collected into module global variables.

We can design a top-level script file that looks like the following code:

from simulator import *

def simulate_SomeStrategy_Flat() -> None:
dealer_rule = Hit17()
split_rule = NoReSplitAces()
table = Table(
decks=6, limit=50, dealer=dealer_rule, split=split_rule, payout=(3, 2)
)
player_rule = SomeStrategy()
betting_rule = Flat()
player = Player(
play=player_rule, betting=betting_rule, max_rounds=100, init_stake=50)

simulate(table, player, Path.cwd()/"data"/"ch14_simulation2a.dat", 100)
if __name__ == "__main__": simulate_SomeStrategy_Flat()

This presents a number of configuration parameters used to create and initialize objects. In this kind of application, the configuration is simply written as code. We've factored out the common processing into a separate function, simulate(), which uses the configured objects, table and player; the Path target; and the number of samples to generate. Rather than parsing and converting strings, the configuration is presented as code.

One potential disadvantage of using Python as the configuration language is the potential complexity of the Python syntax. This is usually an irrelevant problem for two reasons. First, with some careful design, the syntax of the configuration should be simple assignment statements with a few () and , instances.  Second, and more importantly, other configuration files have their own complex syntax, which are distinct from the Python syntax. Using a single language is a net reduction in complexity.

The simulate() function is imported from the overall simulator application. This simulate() function is similar to the following code:

import csv
from pathlib import Path

def simulate(table: Table, player: Player, outputpath: Path, samples: int) -> None:
simulator = Simulate(table, player, samples=samples)
with outputpath.open("w", newline="") as results:
wtr = csv.writer(results)
for gamestats in simulator:
wtr.writerow(gamestats)

This function is generic with respect to the table, player, filename, and number of samples. Given the required configuration objects, it builds the final Simulate instance and collects the resulting data.

A potential difficulty with this kind of configuration technique is the lack of handy default values. The top-level script must be complete, that is, all of the configuration parameters must be present. In most cases, this is not a limitation. In the few cases where default values are important, we'll look at two ways to provide helpful default values.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset