Python изменить текстовый файл по имени аргументов - PullRequest
0 голосов
/ 22 марта 2019

У меня есть текстовый файл ("input.param"), который служит входным файлом для пакета. Мне нужно изменить значение одного аргумента. Необходимо изменить следующие строки:

param1        0.01
model_name    run_param1

Мне нужно найти аргумент param1 и изменить значение 0.01 для диапазона различных значений, в то же время model_name также будет соответственно изменено для другого значения param1. Например, если para1 изменяется на 0,03, то model_name изменяется на 'run_param1_p03'. Ниже приведен пример моего кода:

import numpy as np
import os


param1_range = np.arange(0.01,0.5,0.01)
with open('input.param', 'r') as file :
   filedata = file.read()

for p_value in param1_range:
    filedata.replace('param1        0.01', 'param1        ' + str(p_value))
    filedata.replace('model_name    run_param1', 'model_name    run_param1' + '_p0' + str(int(round(p_value*100))))

   with open('input.param', 'w') as file:
       file.write(filedata)

   os.system('./bin/run_app param/input.param')

Однако это не работает. Я предполагаю, что главная проблема в том, что команда replace не может распознать space. Но я не знаю, как искать аргументы param1 или model_name и изменять их значения.

1 Ответ

1 голос
/ 22 марта 2019

Я редактирую этот ответ, чтобы точнее ответить на исходный вопрос, чего он не сделал адекватно.

Проблема в "Команда replace не может распознать пробел" .Для этого может помочь модуль re, или regex.Ваш документ состоит из записи и ее значения, разделенных пробелами:

param1        0.01
model_name    run_param1

В регулярном выражении общий захват будет выглядеть так:

import re

someline = 'param1        0.01'
pattern = re.match(r'^(\S+)\s+(\S+)$', someline)

pattern.groups()
# ('param1', '0.01')

Регулярное выражение работает следующим образом:

^ захватывает начало строки \S равно любому непробельному символу или что-либо не в ('\t', ' ', '\r', '\n') + указываетодин или несколько как жадный поиск (будет идти вперед, пока шаблон не перестанет совпадать) \s+ равен любой символ пробела (в противоположность \S, обратите внимание на регистр здесь) () указывает группы или какВы хотите сгруппировать свой поиск

Группы позволяют довольно легко распаковать ваши аргументы в переменные, если вы того пожелаете.Чтобы применить это к коду, который у вас уже есть:

import numpy as np 
import re

param1_range = np.arange(0.01,0.5,0.01)
filedata = []

with open('input.param', 'r') as file:
    # This will put the lines in a list
    # so you can use ^ and $ in the regex
    for line in file:
        filedata.append(line.strip()) # get rid of trailing newlines

# filedata now looks like:
# ['param1        0.01', 'model_name    run_param1']

# It might be easier to use a dictionary to keep all of your param vals
# since you aren't changing the names, just the values
groups = [re.match('^(\S+)\s+(\S+)$', x).groups() for x in filedata]

# Now you have a list of tuples which can be fed to dict()
my_params = dict(groups)
# {'param1': '0.01', 'model_name': 'run_param1'}

# Now just use that dict for setting your params
for p_value in param1_range:
    my_params['param1'] = str(p_value)
    my_params['model_name'] = 'run_param1_p0' + str(int(round(p_value*100)))

    # And for the formatting back into the file, you can do some quick padding to get the format you want
    with open('somefile.param', 'w') as fh:
        content = '\n'.join([k.ljust(20) + v.rjust(20) for k,v in my_params.items()])
        fh.write(content)

Заполнение выполняется методами str.ljust и str.rjust, поэтому вы получаете формат, который выглядит следующим образом:

for k, v in dict(groups).items():
    intstr = k.ljust(20) + v.rjust(20)
    print(intstr)

param1                              0.01
model_name                    run_param1

Хотя вы, возможно, могли бы опустить rjust, если бы вы чувствовали такую ​​склонность.

...