Замена строки не записывается в файл - PullRequest
0 голосов
/ 23 мая 2019

Мне нужно отредактировать определенный файл для исследования DoE. Файл в формате:

1 Wall1
roughness 0.0
velocity 0.0
temperature "temperature.file"
########
2 Wall2
roughness 0.0
velocity 0.0
temperature "temperature.file"
########
3 Wall3
roughness 0.0
velocity 0.0
temperature "temperature.file"
########
4 Wall4
roughness 0.0
velocity 0.0
temperature 34.1
########
5 Roof
roughness 0.0
velocity 0.0
temperature "temperature.file"
########

Для DoE я хотел бы изменить одну или несколько записей «temperature.file» (которые являются пространственно изменяющимся температурным полем региона) для каждого случая. Так, например, в случае 2 файл температуры Wall2 будет изменен на «Temperature2.file». Затем программа узнает, что нужно найти новый файл вместо исходного.

Я установил вложенный цикл for, но борюсь с файловым вводом / выводом. Код, который у меня сейчас есть:

if m == 2:
    with open(newfolder2+'/walls.in','r') as file:
        filedata = file.readlines()
        for line in filedata:
            if 'Wall2' in line:
                for line in filedata:
                    if 'temperature' in line:
                        print line
                        line = line.replace('temperature.file','temperature2.file')
                        print line
                        break
#       file.seek(0)

    with open(newfolder2+'/walls.in','w') as file:
        file.writelines(filedata)

Так что, по сути, я хочу найти линию, где происходит "Wall2", затем искать строку с температурой после Wall2, затем изменить ее, и только строку "temperature.file" этой строки на "temperature2.file". Затем выйдите из файла и затем запишите в файл, создав тем самым новый входной файл для этого конкретного случая.

Первая строка печати, которую я имею, распечатывает исходную строку, а код второй строки печати также правильно печатает измененную строку. Однако кажется, что данные файла не были успешно записаны обратно в файл.

Что, кажется, идет не так?

Альтернативный метод, вместо всех вложенных циклов для поиска конкретной строки, я думал, это просто использовать опцию file.seek (). Строки и общая длина файла wall.in останутся прежними, поэтому я могу просто перейти к этой конкретной строке, чтобы изменить строку "temperature.in". Это лучший подход? Я никогда не пробовал этого, поэтому некоторые примеры кода будут с благодарностью.

Спасибо всем большое!

Ответы [ 3 ]

0 голосов
/ 23 мая 2019

вы никогда не назначаете ничего нового для filedata.

, вы можете написать что-то вроде парсера, который знает контекст (здесь: номер стены, в которой вы находитесь).это может выглядеть примерно так:

from io import StringIO

# thie u is needed in python < 3
txt = u"""1 Wall1
roughness 0.0
velocity 0.0
temperature "temperature.file"
########
2 Wall2
roughness 0.0
velocity 0.0
temperature "temperature.file"
########
"""

wall = None
with StringIO(txt) as infile, StringIO() as outfile:
    for line in infile:
        if " Wall" in line:
            wall = int(line[:2])
        if wall == 2:
            if '"temperature.file"' in line:
                line = line.replace('"temperature.file"', '"temperature2.file"')
        outfile.write(line)

    print(outfile.getvalue())

, чтобы действительно читать / записывать ваши файлы, вам нужно изменить строку with на

with open(newfolder2+'/walls.in','r') as infile, 
     open(newfolder2+'/walls.out','w') as outfile:

и удалить строку, содержащую outfile.getvalue().и тогда вам придется переименовать walls.out обратно в walls.in.таким образом, ваш исходный файл не теряется, если программа делает то, что вам не нужно.

это может быть легко адаптировано, если вы хотите изменить другие строки для других Wall s.

0 голосов
/ 23 мая 2019

Здесь происходят две ошибки.

  1. Когда вы выполняете итерацию в цикле for, изменяемая переменная инициализируется локально и изменяется, что фактически не приводит к изменению зацикленного объекта.
>>> a = [5,4,3,7,1]
>>> for i in a:
...     i=2  # this won't change the elements of a!
... 
>>> a
[5, 4, 3, 7, 1]
Как вы его структурировали, второй цикл for будет повторяться по filedata с самого начала снова после нахождения Wall2.Это связано с тем, что цикл for сам не знает, что он выполняется внутри другого цикла for.В конечном итоге вы получите неправильные результаты, даже если исправите 1. Либо используйте итератор, чтобы зациклить filedata, либо используйте f.readline(), который сам является генератором.
filedata=iter(filedata)

Следующий код должен работать:

filedata = []
with open('myfile') as f:
    line = ''
    while 'Wall2' not in line:
        line = f.readline()
        filedata.append(line)
    while 'temperature' not in line:
        line = f.readline()
        filedata.append(line)
    filedata.append(line.replace('temperature.file','temperature2.file'))

with open('myfile', 'w') as f:
    f.writelines(filedata)

Однако я бы этого не делал.Если вы знаете, что файл всегда в одном и том же формате и номер строки всегда будет оставаться постоянным, используйте file.seek.Это должно быть намного быстрее.См. Также Можно ли изменить строки в файле на месте? , если вы хотите изменить файл на месте.

0 голосов
/ 23 мая 2019

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

То, что вы могли бы сделать, это что-то вроде этого, где вы разбили содержимое вашего файла на куски. Поскольку каждый раздел в вашем файле заканчивается символом ########, мы можем использовать его для разбиения файла на куски. Затем вы можете изменить найденный фрагмент и записать его обратно в файловые данные перед сохранением.

with open(newfolder2+'/walls.in', 'r') as file:
filedata = file.read().split("########")
for i, chunk in enumerate(filedata):
    if "Wall2" in chunk:
        chunk = chunk.replace('temperature.file', 'temperature2.file')
        filedata[i] = chunk

with open(newfolder2+'/walls.in', 'w') as file:
    file.writelines("########".join(filedata))
...