load parameters from a file in Python
Solution 1
- If you are open to some other kind of file where you can keep your parameters, I would suggest you to use YAML file.
- The python lib is PyYAML This is how you can easily use it with Python
- For better introduction, look at the wiki article : http://en.wikipedia.org/wiki/YAML
- The benefit is you can read the parameter values as list, maps
- You would love it!
Solution 2
Assuming the params are coming from a safe place (made by you or users, not the internet), just make the parameters file a Python file, params.py
:
Z0 = (0, 0)
k = 0.1
g = 1
Delta = 20
t_end = 300
Then in your code all you need is:
import params
fancy_calculation(10, k=params.k, delta=params.Delta)
The beauty of this is two-fold: 1) simplicity, and 2) you can use the power of Python in your parameter descriptions -- particularly useful here, for example:
k = 0.1
Delta = 20
g = 3 * k + Delta
Alternatively, you could use Python's built-in JSON or ConfigParser .INI parser modules.
Solution 3
As others have mentioned, in Python you can create object attributes dynamically "on the fly". That means you could do something like the following to create Params
objects as they're read-in. I've tried to make the code as data-driven as possible, so relatively flexible.
# maps label to attribute name and types
label_attr_map = {
"Z0:": ["z0", float, float],
"k:": [ "k", float],
"g:": [ "g", float],
"Delta:": [ "D", float],
"t_end:": [ "T", float]
}
class Params(object):
def __init__(self, input_file_name):
with open(input_file_name, 'r') as input_file:
for line in input_file:
row = line.split()
label = row[0]
data = row[1:] # rest of row is data list
attr = label_attr_map[label][0]
datatypes = label_attr_map[label][1:]
values = [(datatypes[i](data[i])) for i in range(len(data))]
self.__dict__[attr] = values if len(values) > 1 else values[0]
params = Params('input.dat')
print 'params.z0:', params.z0
print 'params.k:', params.k
print 'params.g:', params.g
print 'params.D:', params.D
print 'params.T:', params.T
Output:
params.z0: [0.0, 0.0]
params.k: 0.1
params.g: 1.0
params.D: 20.0
params.T: 300.0
Solution 4
Try the following:
def load(self, filename="input.dat"):
d = {"Z0": "z0", "k": "k", "g": "g", "Delta": "D", "t_end": "T"}
FILE = open(filename)
for line in FILE:
name, value = line.split(":")
value = value.strip()
if " " in value:
value = map(float, value.split())
else:
value = float(value)
setattr(self, d[name], value)
Proof that it works:
>>> class A(object): pass
...
>>> a = A()
>>> load(a)
>>> a.__dict__
{'k': 0.10000000000000001, 'z0': [0.0, 0.0], 'D': 20.0, 'g': 1.0, 'T': 300.0}
nos
Hello fellow programmers! I maintain open source software and blog about science and technology in my spare time. Main projects: gita: A command-line tool to manage multiple git repos (1000+ ⭐) blog where I write about math, physics, coding, and hobbies youtube channel: productivity hacks and coding tips
Updated on August 06, 2020Comments
-
nos almost 4 years
I am writing a Python class to model a process and I want to initialized the parameters from a file, say
'input.dat'
. The format of the input file looks like this.'input.dat'
file:Z0: 0 0 k: 0.1 g: 1 Delta: 20 t_end: 300
The code I wrote is the following. It works but appears redundant and inflexible. Is there a better way to do the job? Such as a loop to do readline() and then match the keyword?
def load(self,filename="input.dat"): FILE = open(filename) s = FILE.readline().split() if len(s) is 3: self.z0 = [float(s[1]),float(s[2])] # initial state s = FILE.readline().split() if len(s) is 2: self.k = float(s[1]) # kappa s = FILE.readline().split() if len(s) is 2: self.g = float(s[1]) s = FILE.readline().split() if len(s) is 2: self.D = float(s[1]) # Delta s = FILE.readline().split() if len(s) is 2: self.T = float(s[1]) # end time
-
Ben Hoyt over 12 yearsWhy not JSON or .INI, which are both built into Python's stdlib? Or "import" (see my answer).
-
daydreamer over 12 years@benhoyt, I guess its more about convenience, I am sure your solution works too :)