Редактировать текстовый файл с помощью 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.