Редактировать текстовый файл с помощью Python
Мне нужно обновить текстовый файл всякий раз, когда меняет IP-адрес, а затем запустите несколько команд из оболочки.
-
Создать переменную LASTKNOWN = "212.171.135.53"
Это адрес ip, который мы имеем при написании этого script.
-
Получить текущий IP-адрес. Он будет меняться ежедневно.
-
Создайте переменную CURRENT для нового IP.
-
Сравнить (как строки) CURRENT to LASTKNOWN
-
Если они одинаковы, выйдите()
-
Если они отличаются,
а. "Скопируйте" старый файл конфигурации (/etc/ipf.conf), содержащий IP-адрес LASTKNOWN в /tmp
B. Замените LASTKNOWN на CURRENT в файле /tmp/ipf.conf.
C. Использование подпроцесса "mv/tmp/ipf.conf/etc/ipf.conf"
D. Используя выполнение подпроцесса, "ipf -Fa -f/etc/ipf.conf"
E. Используя выполнение подпроцесса, "ipnat -CF -f/etc/ipnat.conf"
-
Выход()
Я знаю, как делать шаги с 1 по 6. Я падаю на часть редактирования файлов, A → C. Я не могу сказать, какой модуль использовать или должен ли я редактировать файл на месте. Есть так много способов сделать это, я не могу принять решение о наилучшем подходе. Думаю, я хочу самого консервативного.
Я знаю, как использовать подпроцесс, поэтому вам не нужно комментировать это.
Я не хочу заменять целые строки; просто конкретный квадратный квадрат.
Спасибо!
Ответы
Ответ 1
Другим способом простого редактирования файлов является использование модуля fileinput
:
import fileinput, sys
for line in fileinput.input(["test.txt"], inplace=True):
line = line.replace("car", "truck")
# sys.stdout is redirected to the file
sys.stdout.write(line)
Ответ 2
Заменить LASTKNOWN на CURRENT в /etc/ipf.conf
Заменить все сразу
filename = "/etc/ipf.conf"
text = open(filename).read()
open(filename, "w").write(text.replace(LASTKNOWN, CURRENT))
Заменить строку за строкой
from __future__ import with_statement
from contextlib import nested
in_filename, outfilename = "/etc/ipf.conf", "/tmp/ipf.conf"
with nested(open(in_filename), open(outfilename, "w")) as in_, out:
for line in in_:
out.write(line.replace(LASTKNOWN, CURRENT))
os.rename(outfilename, in_filename)
Примечание: "/tmp/ipf.conf" следует заменить на tempfile.NamedTemporaryFile()
или аналогичный
Примечание: код не проверен.
Ответ 3
Вы пытаетесь "атомизировать" обновление содержимого файла, и было много восхитительных пламенных войн по этому вопросу. Но общий шаблон:
1) Запишите новый файл в файл temp и убедитесь, что вы скрылись и закрылись.
2) Используйте средства операционной системы для автоматического переименования временного файла в старый файл.
Теперь вы просто не можете физически переименовать файл в Windows, но, похоже, вы все равно похожи на UNIX-систему. Вы атомарно переименовываете с помощью os.rename().
Ответ 4
Вероятно, самым простым способом было бы открыть файл, используя f = open (имя файла, режим). Затем прочитайте все строки, используя f.readlines() (это вернет список строк, представляющих строки программы).
Затем вы можете искать эти строки, чтобы найти адрес и заменить его новым (с использованием стандартной замены строки, регулярных выражений или любого другого).
В конце вы можете записать строки обратно в файл, используя f.writelines(lines), который удобно возвращает список строк.
ПРИМЕЧАНИЕ. Это не эффективный способ сделать это, это просто самый простой. Пожалуйста,
Пример кода:
f = open(filename, "r")
lines = f.readlines()
# Assume that change_ip is a function that takes a string and returns a new one with the ip changed): example below
ret_lines = [change_ip(lines) for line in lines]
new_file = open(new_filename, "w")
new_file.writelines(lines)
def change_ip(str):
''' Gets a string, returns a new string where the ip is changed '''
# Add implementation, something like: return str.replace(old_ip, new_ip) or something similair.
Ответ 5
После проверки комментариев и бит кода, который вы положили на pastebin, вот рабочее решение. Для начала файл /tmp/iiiipf.conf содержит:
Simply a test file 175.48.204.168
And two times 175.48.204.168 on this line 175.48.204.168
Done.
После запуска кода файл /tmp/iiiipf.conf содержит:
Simply a test file 10.73.144.112
And two times 10.73.144.112 on this line 10.73.144.112
Done.
И вот тестовый рабочий код с моими материалами, объединенными в ваш код pastebin:
import socket
import fileinput
import subprocess
import string
import re
CURRENT = socket.getaddrinfo(socket.gethostname(), None)[0][4][0]
LASTKNOWN = '175.48.204.168'
if CURRENT == LASTKNOWN:
print 'Nevermind.'
subprocess.sys.exit()
else:
cf = open("/tmp/iiiipf.conf", "r")
lns = cf.readlines()
# close it so that we can open for writing later
cf.close()
# assumes LASTKNOWN and CURRENT are strings with dotted notation IP addresses
lns = "".join(lns)
lns = re.sub(LASTKNOWN, CURRENT, lns) # This replaces all occurences of LASTKNOWN with CURRENT
cf = open("/tmp/iiiipf.conf", "w")
cf.write(lns)
cf.close()
Этот бит кода будет делать то, что вам нужно, даже если IP-адрес используется несколько раз в файле конфигурации. Он также изменит его в строках комментариев.
Этот метод не требует копирования в /tmp и использует один менее вызов подпроцесса при перезапуске брандмауэра и NAT.