Найти - Пользователи
Полная версия: Парсинг конфигурационного файла. regexp или другое
Начало » Python для новичков » Парсинг конфигурационного файла. regexp или другое
1 2 3 4 5 6
s0rg
Такой вариант понятен - я имею ввиду ситуацию когда нужно изменить какой-либо параметр (или группу) в зависимости от значения других параметров (или группы)
Ed
Это уже логика. Все равно нужно будет править код, если хотите ее запрограммировать.
Ed
По-моему мы увлеклись. может спросим топикстартера чего ему нужно?
s0rg
Я так понял, что ТС решил уже проблему )
Просто решил подискутировать на тему лучшего варианта решения )
pyuser
Ed
По-моему мы увлеклись.
Здесь бы +1 поставить :)…..
aivs
Не, не проблему еще не решил, я выложу готовый вариант, с обоснованием, почему выбрал тот, а не иной метод. Сейчас времени в обрез, готовлюсь к выставке hi tech building 2011.
По теме, две задачи было, первая - читать значения параметров(сделано), вторая - оптимально редактировать конфиг, не изменяя структуру. Как выяснилось из дискуссии, в моем варанте лучше работать со славарем, чем с списком. На данный момент, задача: работать с конфигом с помощью словаря и не изменять структуру файла.
aivs
Вообщем я закончил, много работы было, некогда питоном было заниматься, но я собрался и дописал свою программу.
Программа работает в ArchLinux и меняет настройки сети, чтобы изменить настройки сети, она правит два файла /etc/rc.conf и /etc/resolv.conf.
Я поставил перед собой задачу не использовать модуль re и дополнительные модули, которые не входят в стандартный набор python.
Из дополнительного использовал только PyQt.
Итак вот он мой шедевр, повторюсь, парсинг конфигов не использует re.



#!/usr/bin/python

# pyarchnetcgf.py
# Программа на QT4 для редактирования сетевых настроек в ArchLinux

import sys, os
from PyQt4 import QtGui, QtCore
# Требуется для получения вывода из ifconfig
from subprocess import Popen, PIPE

RCCONF = "/etc/rc.conf"
RESOLVCONF = "/etc/resolv.conf"

class ArchNetCfg(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)

self.setWindowTitle("Сетевые настройки")

###Радио кнопки Статически и Автоматически###
self.radioStatic = QtGui.QRadioButton("Статически", self)
self.radioAuto = QtGui.QRadioButton("Автоматически", self)
self.radioStatic.setChecked(True)

###Метки###
ipLabel = QtGui.QLabel("IP-адрес")
maskLabel = QtGui.QLabel("Маска")
gatewayLabel = QtGui.QLabel("Шлюз")
dns1Label = QtGui.QLabel("DNS1")
dns2Label = QtGui.QLabel("DNS2")
dns3Label = QtGui.QLabel("DNS3")
macLabel = QtGui.QLabel("MAC-адрес")

###Подсказки для меток###
ipLabel.setToolTip("IP-адрес - уникальный сетевой адрес узла (компьютера) в компьютерной сети.\nЕго можно узнать у вашего провайдера или системного администратора.")
maskLabel.setToolTip("Маска подсети - битовая маска, определяющая, какая часть IP-адреса \nузла сети относится к сети, а какая - к адресу узла в этой сети.")
gatewayLabel.setToolTip("Сетевой шлюз - предоставляет доступ в локальную сеть или интернет")
dns1Label.setToolTip("Сервер предоставляющий IP-адрес хоста по его имени")
dns2Label.setToolTip("Сервер предоставляющий IP-адрес хоста по его имени")
dns3Label.setToolTip("Сервер предоставляющий IP-адрес хоста по его имени")

###Поля для правки адресов###
self.ipEdit = QtGui.QLineEdit(self.read_setting_from_rcconf("address"))
self.maskEdit = QtGui.QLineEdit(self.read_setting_from_rcconf("netmask"))
self.gatewayEdit = QtGui.QLineEdit(self.read_setting_from_rcconf("gateway"))
self.dns1Edit = QtGui.QLineEdit(self.read_resolvconf(0))
self.dns2Edit = QtGui.QLineEdit(self.read_resolvconf(1))
self.dns3Edit = QtGui.QLineEdit(self.read_resolvconf(2))
self.macAddress = QtGui.QLineEdit(self.get_mac('eth0'))
self.macAddress.setDisabled(True)

###Кнопки сохранить и отмена###
self.buttonBox = QtGui.QDialogButtonBox(self)
self.save = self.buttonBox.addButton(self.buttonBox.Save)
self.cancel = self.buttonBox.addButton(self.buttonBox.Cancel)


###Расстановка элементов по сетки###
hboxRadio = QtGui.QHBoxLayout()
hboxRadio.addWidget(self.radioStatic)
hboxRadio.addWidget(self.radioAuto)

grid = QtGui.QGridLayout()
grid.setSpacing(5)

grid.addWidget(ipLabel, 1, 0)
grid.addWidget(self.ipEdit, 1, 1)

grid.addWidget(maskLabel, 2, 0)
grid.addWidget(self.maskEdit, 2, 1)

grid.addWidget(gatewayLabel, 3, 0)
grid.addWidget(self.gatewayEdit, 3, 1)

grid.addWidget(dns1Label, 4, 0)
grid.addWidget(self.dns1Edit, 4, 1)

grid.addWidget(dns2Label, 5, 0)
grid.addWidget(self.dns2Edit, 5, 1)

grid.addWidget(dns3Label, 6, 0)
grid.addWidget(self.dns3Edit, 6, 1)

grid.addWidget(macLabel, 7, 0)
grid.addWidget(self.macAddress, 7, 1)

hboxButton = QtGui.QHBoxLayout()
hboxButton.addStretch(1)
hboxButton.addWidget(self.buttonBox)

vbox = QtGui.QVBoxLayout()
vbox.addLayout(hboxRadio)
vbox.addLayout(grid)
vbox.addLayout(hboxButton)

###Геометрия окна###
self.setLayout(vbox)
self.setGeometry(300,300,0, 0)

###Сигналы и слоты###
self.connect(self.cancel, QtCore.SIGNAL('clicked()'), QtGui.qApp, QtCore.SLOT('quit()'))
self.connect(self.save, QtCore.SIGNAL('clicked()'), self.saveChanges)
self.connect(self.radioAuto, QtCore.SIGNAL('toggled(bool)'), self.disableAll)
self.connect(self.radioStatic, QtCore.SIGNAL('toggled(bool)'), self.enableAll)

"""Сделать элементы не активными"""
def disableAll(self):

self.ipEdit.setDisabled(True)
self.maskEdit.setDisabled(True)
self.gatewayEdit.setDisabled(True)
self.dns1Edit.setDisabled(True)
self.dns2Edit.setDisabled(True)
self.dns3Edit.setDisabled(True)

"""Сделать элементы активными"""
def enableAll(self):

self.ipEdit.setDisabled(False)
self.maskEdit.setDisabled(False)
self.gatewayEdit.setDisabled(False)
self.dns1Edit.setDisabled(False)
self.dns2Edit.setDisabled(False)
self.dns3Edit.setDisabled(False)

"""Сохранение настроек"""
def saveChanges(self):

# Значения всех полей
ip = self.ipEdit.text()
mask = self.maskEdit.text()
gateway = self.gatewayEdit.text()
dns1 = self.dns1Edit.text()
dns2 = self.dns2Edit.text()
dns3 = self.dns3Edit.text()

# Остановить сеть!!!
os.system("/etc/rc.d/network stop")

if self.radioAuto.isChecked():

#Записать автоматические настройки
self.rcconf_edit("address","")
self.rcconf_edit("netmask","")
self.rcconf_edit("gateway","")

else:

# Записать настройки вручную
self.rcconf_edit("address",ip)
self.rcconf_edit("netmask",mask)
self.rcconf_edit("gateway",gateway)

# Записать DNS адрес
self.writedns(dns1, dns2, dns3)

# Запустить сеть!!!
os.system("/etc/rc.d/network start")

# После сохранения, выходим
sys.exit()


""" Функция считывает значение у параметра из rc.conf,
вызывается: read_setting_from_rcconf("имя параметра")"""
def read_setting_from_rcconf(self,param):

config = open(RCCONF).readlines()

# Вычисляем номер строки, которая начинается с имени параметра
num_line = 0 #Номер строки
for line in config:
# Если строка N num_line начинается со слова param
if config[num_line].startswith(param):
break
num_line+=1

# Разбиваем строку на слова
param_sett = config[num_line].split("=")

# Очищаем значение параметра от пробелом, и возвращаем
return param_sett[1].strip()

""" Функция редактирования конфигурационного файла rc.conf,
вызывается: rcconf_edit("параметр","значение") """
def rcconf_edit(self,param, setting):
# Читаем все строки в файле
config = open(RCCONF).readlines()

# Вычисляем номер строки, которая начинается с gateway
num_line = 0 #Номер строки
for line in config:
# Если строка N num_line начинается со слова param
if config[num_line].startswith(param):
break
num_line+=1

# Разбиваем строку на слова
param_sett = config[num_line].split("=")

# Очищаем значение параметра от пробелом и сохраняем в переменную old_setting
old_setting = param_sett[1].strip()

# Заменяем строку "параметр = значение" на новую
param_sett[1] = setting + "\n"
config[num_line] = '='.join(param_sett)

# Записываем новый конфиг в файл
with open(RCCONF, 'w') as config_write:
config_write.writelines(config)

""" Функция считывает все dns адреса из resolv.conf и возвращает запрашиваемый по номеру"""
def read_resolvconf(self,num_dns):

config = open(RESOLVCONF).readlines()

# Вычисляем номер строки, которая начинается с имени параметра
num_line = 0 # Номер строки
nameserver_list = [] # Список в котором будут храниться dns адреса
for line in config:
# Если строка N num_line начинается со слова nameserver и имеет продолжение
if config[num_line].startswith("nameserver") and len(config[num_line]) > 11:
# То разбиваем строку на подстроки
a = config[num_line].split()

# Сохраняем значение в список
nameserver_list.append(a[1])
num_line+=1

# Возвращаем dns адрес. Если num_dns задан неверный, то возвращается ничего
try:
return nameserver_list[num_dns]
except IndexError:
return ""

def writedns(self, dns1, dns2, dns3):
# Открыли на запись
with open(RESOLVCONF, 'w') as resolv:
all_dns_address = ('')

# Записать в all_dns_address все используемые днс адреса, пустые поля игнорируются
for dns in dns1, dns2, dns3:
if len(dns) > 0 :
all_dns_address = all_dns_address + 'nameserver %s\n' %(dns)

# Добавить к комментариям список днс адресов
text_in_resolv = ('# Generadet by pyarchnetcfg\n'
'# /etc/resolv.conf.head can replace this line\n'
'%s'
'# /etc/resolv.conf.head can replace this line\n' %(all_dns_address))
# Записать сформированную строку в файл
resolv.write(text_in_resolv)

""" Функция получения mac адреса, возвращает mac адрес """
def get_mac(self, interface):

# Выполнить ifconfig eth0
p1 = Popen(['ifconfig', interface], stdout=PIPE)
# и записать вывод в output в виде строки
output = str(p1.communicate()[0])
# Позиция слова ether в строке
pos_word = output.find('ether')
# mac адрес начинается c 6 символа после начала слова ether и кончается на 23 символе после начала слова ether
return output[pos_word+6:pos_word+23]




app = QtGui.QApplication(sys.argv)
qb = ArchNetCfg()
qb.show()
sys.exit(app.exec_())
При написании этой программы, я многому научился, всем спасибо.
Единственное, что я не понял, это почему я не могу вставить строки документации в функции, пришлось их вынести из функций.
После НГ начну писать оболочку для carpc.
py.user.next
aivs
    def read_setting_from_rcconf(self,param):

config = open(RCCONF).readlines()

# Вычисляем номер строки, которая начинается с имени параметра
num_line = 0 #Номер строки
for line in config:
# Если строка N num_line начинается со слова param
if config[num_line].startswith(param):
break
num_line+=1

# Разбиваем строку на слова
param_sett = config[num_line].split("=")

# Очищаем значение параметра от пробелом, и возвращаем
return param_sett[1].strip()
что-то много букв

    def read_setting_from_rcconf(self, param):
with open(RCCONF) as f:
for line in f:
if line.startswith(param)
break
sett = line.split('=')[1].strip()
return sett
o7412369815963
> Я поставил перед собой задачу не использовать модуль re и дополнительные модули, которые не входят в стандартный набор python.
дак вроде re как раз входит в стандартный набор.
aivs
py.user.next Спасибо, для меня замечания такого рода очень важны, компактный и понятный код нужно учиться с самого начала!

o7412369815963] Не использовать модуль re и не использовать дополнительные модули. Первое и второе сразу.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB