Hello,
I’m writing a simple simulation program, and I want the input parameters to be read from a text file at runtime. My strategy is to read all of the parameters into a dictionary, which works, but feels very clumsy. I’m curious to know if anyone else has a better solution.
The text file containing the inputs would look something like this:
# comments are indicated by '#'
num1 = 10
num2 = 4.6
num3 = 1e20
bool1 = true
bool2 = F # interpreted as false
option1 = string1
These parameters are parsed and stored in a dictionary of the form:
params = Dict(
"num1" => 10,
"num2" => 14.6,
"num3" => 1e20,
"bool1" => true,
"bool2" => false,
"option1" => "string1"
)
The difficulty arises when I go to use these parameters, because I need to reference the dictionary every time I need one of these options. A simple calculation using the above values could look like:
params.num1 * params.num2 * params.num3
Which is messy to say the least.
In the actual case, my I/O code is contained in a module separate from the code that uses the simulation parameters.
Thanks in advance,
Patrick
PS: For anyone who may be interested, here is the full parsing function I’ve written:
Summary
"""
parseinputs(filename, dsettings)
Parses parameters from a text file and stores them as a dictionary.
Opens the file specified by `filename`, which must include the path.
Parameters must be setting-value pairs delimited by `=`.
Blank lines are ignored, as is any text following `#`.
Whitespace does not matter, nor does text case.
Booleans can be entered as "true/false", "T/F", or "1/0".
A dictionary `(dsettings)` containing all parameters must be provided. Another
dictionary is returned containing those same parameters, with values different
from the default only if a matching identifier was found in the input file.
"""
function parseinput(filename::AbstractString, dsettings::Dict=defaults)
usettings = copy(dsettings)
for line in eachline(filename)
line = lowercase(strip(line))
if isempty(line) || line[1] == '#'
continue
end
setting, value = split(line, ['=','#'], keepempty=false)
setting = strip(setting)
value = strip(value)
if setting in keys(usettings)
dtype = typeof(dsettings[setting])
if dtype == Bool
if value == "false" || value == 'f' || value == 0
value = false
elseif value == "true" || value == 't' || value == 1
value = true
else
error(string("Unable to parse value entered for ", setting))
end
elseif dtype <: Number
value = tryparse(dtype, value)
if isnothing(value)
error(string("Unable to parse value entered for ", setting))
end
elseif dtype <: AbstractArray
value = split(value, [',',' '], keepempty=false)
value = tryparse.(Float64, value)
end
usettings[setting] = value
end
end
return usettings
end