Найти - Пользователи
Полная версия: Парсинг конфигурационного файла. regexp или другое
Начало » Python для новичков » Парсинг конфигурационного файла. regexp или другое
1 2 3 4 5 6
aivs
Есть конфигурационный файл rc.conf из Arch Linux
#
# /etc/rc.conf - Main Configuration for Arch Linux
#

# -----------------------------------------------------------------------
# LOCALIZATION
# -----------------------------------------------------------------------
LOCALE="ru_RU.UTF-8"
HARDWARECLOCK="localtime"
TIMEZONE="Europe/Moscow"
KEYMAP="us"
CONSOLEFONT=ter-u16b
CONSOLEMAP=
USECOLOR="yes"

# -----------------------------------------------------------------------
# HARDWARE
# -----------------------------------------------------------------------
MOD_AUTOLOAD="yes"
MODULES=()

# Scan for LVM volume groups at startup, required if you use LVM
USELVM="no"

# -----------------------------------------------------------------------
# NETWORKING
# -----------------------------------------------------------------------
HOSTNAME="myhost"
interface=eth0
address=
netmask=
gateway=

# -----------------------------------------------------------------------
# DAEMONS
# -----------------------------------------------------------------------
DAEMONS=(syslog-ng @network ntpd crond dbus sshd samba transmissiond)
Я пишу программу сетевой настройки, для этого из rc.conf нужно прочитать параметры: interface=eth0, address=, netmask=, gateway=,
и если нужно, внести изменения: interface=eth0, address=192.168.1.100, netmask=255.255.255.0, gateway=192.168.1.1 .
Делал такое с использованием sed, т.е. regexp'ом.
Вопрос, может в python есть какой нибудь специальный модуль для работы с конфигурационными файлами ??
magnet85
Из стандартной библиотеки configparser смотрели? http://docs.python.org/library/configparser.html
PooH
Стандартный ConfigParser не может читать ini файлы без секций, для обхода есть такое решение http://stackoverflow.com/questions/2819696/parsing-properties-file-in-python/2819788
aivs
Пытаюсь обойти секции с помощью предложенного метода, но происходит ошибка.
#!/usr/bin/python
# parse_rc.conf.py
import configparser

class FakeSecHead(object):
def __init__(self, fp):
self.fp = fp
self.sechead = '[asection]\n'
def readline(self):
if self.sechead:
try: return self.sechead
finally: self.sechead = None
else: return self.fp.readline()

config = configparser.SafeConfigParser()
config.readfp(FakeSecHead(open('rc.conf')))
config.items('asection')
Вот ошибка
[aivs@myhost python]$ ./parse_rc.conf.py 
Traceback (most recent call last):
File "./parse_rc.conf.py", line 16, in <module>
config.readfp(FakeSecHead(open('rc.conf')))
File "/usr/lib/python3.2/configparser.py", line 753, in readfp
self.read_file(fp, source=filename)
File "/usr/lib/python3.2/configparser.py", line 708, in read_file
self._read(f, source)
File "/usr/lib/python3.2/configparser.py", line 994, in _read
for lineno, line in enumerate(fp, start=1):
TypeError: 'FakeSecHead' object is not iterable
[aivs@myhost python]$
В чем проблема ??
Ed
Проблема в том, что грязный хак, который вам посоветовали был для второго Питона.
Для третьего все проще:
import configparser

parser = configparser.SafeConfigParser()
parser.read_string("[section]\n" + open('rc.conf').read())
print(parser.items('section'))
А для второго нужно сделать тоже самое, что сделали в третьем - читать через StringIO. Кстати, работать такое будет и в третьем.
aivs
Ed спасибо, блин, а я перевод сделал для 2.7!

А возможно ли этим парсером не только читать, но и записывать в конфиг с таким стилем не испортив его, попробовал записать в этот конфиг, вот код
#!/usr/bin/python
# parse_rc.conf.py
import configparser

config = configparser.SafeConfigParser()
config.read_string("[section]\n" + open('rc.conf').read())
config.set('section', 'gateway', '192.168.1.1')
with open('rc.conf', 'w') as configfile:
config.write(configfile)
Получил такой конфиг:
[section]
locale = "ru_RU.UTF-8"
hardwareclock = "localtime"
timezone = "Europe/Moscow"
keymap = "us"
consolefont = ter-u16b
consolemap =
usecolor = "yes"
mod_autoload = "yes"
modules = ()
uselvm = "no"
hostname = "myhost"
interface = eth0
address =
netmask =
gateway = 192.168.1.1
daemons = (syslog-ng @network ntpd crond dbus sshd samba transmissiond)
А мне всего то надо было изменить значение у gateway.
Ed
aivs
А возможно ли этим парсером не только читать, но и записывать в конфиг с таким стилем не испортив его
Если нужно убрать пробелы вокруг = и вывод секции убрать, то возможно, пронаследовав свой парсер от SafeConfigParser и немного исправив метод write. Если я чего-то недосмотрел, то скажите что еще нужно сделать.
Чтобы вам жизнь медом не казалась попробуйте это сделать самостоятельно и показать здесь результат. А я поправлю, если что-то пойдет не так. Вопросы приветствуются.

aivs
А мне всего то надо было изменить значение у gateway.
Кхе-кхе. Не забывайте, что это парсер .ini файлов, а не того, что вы ему подсовываете. И в этом качестве он свою задачу выполняет.
Поэтому у вас 3 пути - либо изгибать существующий парсер под ваши нужды, либо писать свой, либо найти готовый.
aivs
Рассматривая второй вариант, написать свой парсер, т.к. я еще учусь, многих простых вариантов решения не вижу.
Задача:
Изменять значения в конфиге типа:
# Комментарий
Параметр_1 = значение_1
Параметр_2 = значение_2
Мой алгоритм:
1) Считать весь файл с помощью readlines
2) Изменить нужную строку (самое сложное)
3) Записать полученное в файл

По пункту 2 нуждаюсь в помощи. Например мне нужно найти строку начинающуюся с gateway = и изменить ее на gateway = 192.168.1.1, как ?
Ed
Я бы попользовал регекспы. Читайте здесь: http://docs.python.org/py3k/library/re.html
s0rg
Прочитать файл по-строчно.
Разбить строку по ‘=’ на две части - имя и значение.
Засунуть в словарь, используя имя как ключ.
Чтобы теперь прочитать значение то используете my_dict
Запись - проходите по элементам словаря склеиваете ключ + ‘ = ’ + значение, добавляете перевод строки, пишите обратно.
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