загрузить параметры из файла в Python - PullRequest
12 голосов
/ 15 декабря 2011

Я пишу класс Python для моделирования процесса и хочу инициализировать параметры из файла, скажем, 'input.dat'.Формат входного файла выглядит следующим образом.

'input.dat' file:

Z0: 0 0
k: 0.1
g: 1
Delta: 20
t_end: 300

Код, который я написал, следующий.Это работает, но выглядит избыточным и негибким.Есть ли лучший способ сделать работу?Например, цикл, выполняющий readline () и затем соответствующий ключевому слову?

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

Ответы [ 9 ]

19 голосов
/ 16 декабря 2011

Предполагая, что параметры приходят из безопасного места (созданного вами или пользователями, а не из Интернета), просто сделайте файл параметров файлом Python, params.py:

Z0 = (0, 0)
k = 0.1
g = 1
Delta = 20
t_end = 300

Тогда в вашем коде все, что вам нужно:

import params
fancy_calculation(10, k=params.k, delta=params.Delta)

Красота этого двояка: 1) простота и 2) вы можете использовать мощь Python в своих описаниях параметров - особенно полезно здесь, например:

k = 0.1
Delta = 20
g = 3 * k + Delta

В качестве альтернативы вы можете использовать встроенные в Python JSON или ConfigParser .INI parser модули.

14 голосов
/ 16 декабря 2011
  • Если вы открыты для какого-либо другого файла, в котором вы можете сохранить свои параметры, я бы предложил вам использовать файл YAML .
  • Python lib PyYAML Это , как вы можете легко использовать его с Python
  • Для лучшего ознакомления смотрите статью в вики: http://en.wikipedia.org/wiki/YAML
  • Преимущество заключается в том, что вы можете читать значения параметров в виде списка, карты
  • Тебе бы это понравилось!
1 голос
/ 16 декабря 2011

Как уже упоминалось, в Python вы можете динамически создавать атрибуты объекта " на лету ". Это означает, что вы можете сделать что-то вроде следующего, чтобы создать Params объекты, когда они читаются. Я пытался сделать код максимально управляемым данными, чтобы он был относительно гибким.

# 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

Выход:

params.z0: [0.0, 0.0]
params.k: 0.1
params.g: 1.0
params.D: 20.0
params.T: 300.0
1 голос
/ 16 декабря 2011

Попробуйте следующее:

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)

Доказательство того, что это работает:

>>> 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}
0 голосов
/ 16 декабря 2011

Вот еще один

def splitstrip(s):
    return s.split(':')[1].strip()

with open('input.dat','r') as f:
    a.z0 = [float(x) for x in splitstrip(f.readline()).split(' ')]
    a.k, a.g, a.D, a.T = tuple([float(splitstrip(x)) for x in f.read().rstrip().split('\n')])

;)

0 голосов
/ 16 декабря 2011

Объекты Python имеют встроенный член __dict__.Вы можете изменить его, а затем ссылаться на свойства как obj.key.

class Data(object):
  def __init__(self, path='infile.dat'):
    with open(path, 'r') as fo:
      for line in fo.readlines():
        if len(line) < 2: continue

        parts = [s.strip(' :\n') for s in line.split(' ', 1)]
        numbers = [float(s) for s in parts[1].split()]

        # This is optional... do you want single values to be stored in lists?
        if len(numbers) == 1: numbers = numbers[0]
        self.__dict__[parts[0]] = numbers
        # print parts  -- debug

obj = Data('infile.dat')
print obj.g
print obj.Delta
print obj.Z0

В конце мы распечатаем несколько ключей.Вот их вывод.

1.0
20.0
[0.0, 0.0]

Для согласованности вы можете удалить строку, помеченную как «необязательную» в моем коде, и иметь все объекты в списках - независимо от того, сколько у них элементов.Это значительно облегчит их использование, потому что вам не нужно беспокоиться о obj.g[0] возврате ошибки.

0 голосов
/ 16 декабря 2011

Примерно так:

def load(self,filename="input.dat"):

    # maps names to number of fields they need
    # only necessary for variables with more than 1 field
    argmap = dict(Z0=2)

    # maps config file names to their attribute names on the object
    # if name is the same both places, no need
    namemap = dict(Z0="z0", Delta="D", t_end="T")

    with open(filename) as FILE:
        for line in FILE:
            s = line.split()
            var = s[0].rstrip(":")
            try:
                val = [float(x) for x in s[1:]]
            except ValueError:
                continue
            if len(val) == varmap.get(var, 1):
               if len(val) == 1:
                   val = val[0]
               setattr(self, namemap.get(var, var), val)
0 голосов
/ 16 декабря 2011

Возможно, это может дать вам то, что вам нужно:

def load(self,filename='input.dat'):
    with open(filename) as fh:
        for line in fh:
           s = line.split()
           if len(s) == 2:
               setattr(self,s[1],s[2])
           elif len(s) == 3:
               setattr(self,s[1],s[2:])

Я также не включал проверку ошибок, но setattr очень удобно.

0 голосов
/ 15 декабря 2011

Вы можете зациклить строки в файле следующим образом:

for line in FILE:
    s = line.split
    var = s[0]
    if var == 'z0:':
        self.z0 = [float(s1), float(s2)]
    elif var == 'k:':
         etc. 

и т. Д.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...