Я пытаюсь создать дочерние сценарии из одного родительского сценария, в котором изменено несколько параметров (48 дочерних сценариев, поэтому предпочтительна автоматизация). Мое намерение состоит в том, чтобы запускать различные сценарии Modelica как отдельные задания Slurm. Обычно я делаю это с помощью языка сценариев Modelica, но поскольку мне нужно отправлять каждый сценарий индивидуально, мне придется создать несколько сценариев. Псевдокод следующий. Примечание. Строки поиска уникальны.
load('model.mo') # modelica file, parent script
# change the control strategy in the script
for i in ['control_1', 'control_2', 'control_3', 'control 4']:
# change the amount of electricity generation
find and replace r'moduleName = "control"' with 'moduleName = control_' + str(i)
for j in [3, 7]:
find and replace '.CombiTimeTable solar_data(columns = {2}' with '.CombiTimeTable solar_data(columns = {' + str(j) + '}'
# change the battery size
for k in [2000000000, 4000000000, 6000000000]:
find and replace 'Storage.Battery BESS(EMax = 2000000000, SOC_start = 0.5, pf = 0.9)' with 'Storage.Battery BESS(EMax = ' + str(k) + ', SOC_start = 0.5, pf = 0.9)'
for l in ['4', '8']:
find and replace '.CombiTimeTable ev_data(columns = {2}' with '.CombiTimeTable ev_data(columns = {' + str(i) + '}'
export('child_model_#.mo')
Моя цель — изменить фактический текст каждого нового скрипта, а не только переменные. Я не уверен, следует ли мне использовать Python, Bash или что-то еще для этой задачи, тем более что я изменяю файл, отличный от .txt
.
Не знаком с Modelica, но стандартным решением на любом языке было бы параметризовать скрипт и каким-то образом передать параметры в командной строке.
@Manfred да, строки поиска уникальны, но я не знаю, как выполнить простую замену строк. Моя цель - автоматизировать поиск и замену.
@tripleee Я согласен, но я не могу изменить сценарий, так как мне нужно запускать каждый файл .mo индивидуально, поскольку я буду выполнять задание slurm.
Ничто из этого не кажется особенно сложным, но внутренний цикл будет перезаписывать результаты внешнего цикла на каждой итерации. Или вы имеете в виду, что #
в имени файла экспорта должна быть комбинацией значений i
, j
, k
и l
?
Если я смогу правильно угадать, что вы хотите, ваш псевдокод на самом деле очень близок к допустимому коду Python.
Я предполагаю, что model.mo
на самом деле является текстовым файлом, и это «не-.txt
» в вашем вопросе просто относится к расширению .mo
. Python (или Slurm, или, предположительно, Modelica) не заботится о том, как вы называете свои файлы; расширение — это чисто человеческое соглашение на разумных платформах. (Я сознательно формулирую это так, чтобы исключить Windows.)
with open('model.mo') as modelica:
script = modelica.read()
# did you really want a space instead of an underscore in 'control 4'?
for i in ['control_1', 'control_2', 'control_3', 'control 4']:
ivar = script.replace(
'moduleName = "control"',
# guessing you wanted to keep the double quotes around the name here
# this generates "control_control_1"; maybe you meant to omit the control_ prefix?
f'moduleName = "control_{i}"')
for j in [3, 7]:
jvar = ivar.replace(
'.CombiTimeTable solar_data(columns = {2}',
f'.CombiTimeTable solar_data(columns = {{{j}}}')
for k in [2000000000, 4000000000, 6000000000]:
kvar = jvar.replace(
'Storage.Battery BESS(EMax = 2000000000, SOC_start = 0.5, pf = 0.9)',
f'Storage.Battery BESS(EMax = {k}, SOC_start = 0.5, pf = 0.9)')
for l in ['4', '8']:
lvar = kvar.replace(
'.CombiTimeTable ev_data(columns = {2}',
# guessing you meant to keep the braces, and you wanted l, not i?
f'.CombiTimeTable ev_data(columns = {{{l}}}')
# Guessing as to what exactly the file name should be
with open(f'child_model_{i}_{j}_{k}_{l}.mo', 'w') as child:
child.write(lvar)
В частности, обратите внимание, как f'strings'
позволяет интерполировать переменные с помощью {variable}
. Обозначение {{
вставляет буквальную открывающую скобку и }}
одну буквальную закрывающую скобку. Существует множество вариантов форматирования интерполированных переменных и выражений; например, {j:02}
выдаст значение j
, состоящее как минимум из двух цифр и при необходимости дополняющее ведущими нулями.
Таким образом, ваши попытки + str(j) +
тоже будут работать нормально; это просто намного более неуклюже.
Я добавил комментарии, в которых мне нужно было угадать, чего вы на самом деле хотите.
Номинально использование круглых круглых скобок вместо квадратных скобок вокруг перечислений было бы немного более эффективным, но вряд ли это здесь является серьезной проблемой. Меня больше всего беспокоит то, соответствуют ли имена сгенерированных файлов тому, что вы хотели. Если вы хотите сократить, возможно, используйте словарь, например
abbrev_k = {
"2B": 2_000_000_000,
"4B": 4_000_000_000,
"6B": 6_000_000_000
}
...
for k in abbrev_k.keys():
kvar = jvar.replace(
'Storage.Battery BESS(EMax = 2000000000, SOC_start = 0.5, pf = 0.9)',
f'Storage.Battery BESS(EMax = {abbrev_k[k]}, SOC_start = 0.5, pf = 0.9)'
использовать аббревиатуру 2B
в имени файла, но преобразовать ее в числовое значение 2 000 000 000 в сгенерированном файле.
Демо: https://ideone.com/cP7KRx
Вы заметите, что мы используем script
для хранения содержимого исходного скрипта, а затем при первой замене мы создаем его копию в ivar
с измененной управляющей строкой, а затем продолжаем создавать новые переменные jvar
, kvar
, lvar
с модифицированная копия в остальной части сценария.
Что для вас означает изменение файла, отличного от .txt? Если речь идет только о расширении имени файла: это не имеет значения. Если содержимое представляет собой текст, вы можете выполнить простую замену строк при условии, что ваши строки поиска уникальны. Если это не так, вам следует предоставить более подробную информацию. В любом случае, вы не задали вопрос, так чего вы ожидаете от нас ответа?