Создайте несколько измененных версий сценария для отправки в кластер

Я пытаюсь создать дочерние сценарии из одного родительского сценария, в котором изменено несколько параметров (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.

Что для вас означает изменение файла, отличного от .txt? Если речь идет только о расширении имени файла: это не имеет значения. Если содержимое представляет собой текст, вы можете выполнить простую замену строк при условии, что ваши строки поиска уникальны. Если это не так, вам следует предоставить более подробную информацию. В любом случае, вы не задали вопрос, так чего вы ожидаете от нас ответа?

Manfred 27.05.2024 08:28

Не знаком с Modelica, но стандартным решением на любом языке было бы параметризовать скрипт и каким-то образом передать параметры в командной строке.

tripleee 27.05.2024 09:13

@Manfred да, строки поиска уникальны, но я не знаю, как выполнить простую замену строк. Моя цель - автоматизировать поиск и замену.

Luis Enriquez-Contreras 27.05.2024 19:12

@tripleee Я согласен, но я не могу изменить сценарий, так как мне нужно запускать каждый файл .mo индивидуально, поскольку я буду выполнять задание slurm.

Luis Enriquez-Contreras 27.05.2024 19:13

Ничто из этого не кажется особенно сложным, но внутренний цикл будет перезаписывать результаты внешнего цикла на каждой итерации. Или вы имеете в виду, что # в имени файла экспорта должна быть комбинацией значений i, j, k и l?

tripleee 27.05.2024 22:01
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
5
80
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Если я смогу правильно угадать, что вы хотите, ваш псевдокод на самом деле очень близок к допустимому коду 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 с модифицированная копия в остальной части сценария.

Другие вопросы по теме