LINUX.ORG.RU

Как в Python 2.7.13 изменить INI-файл с субсекциями?

 ,


0

1

Имеется INI-файл с вот такой структурой:

...
[AC]
icon=battery-charging

[AC][DPMSControl]
idleTime=3600

[AC][HandleButtonEvents]
lidAction=64
powerButtonAction=8

[Battery]
icon=battery-060

[Battery][DPMSControl]
idleTime=300

[Battery][HandleButtonEvents]
lidAction=64
powerButtonAction=16

[LowBattery]
icon=battery-low

[LowBattery][BrightnessControl]
value=30

[LowBattery][HandleButtonEvents]
lidAction=64
powerButtonAction=16
...

Здесь видно, что HandleButtonEvents - это «субсекция», а основная секция задается перед субсекцией в той же строке. Не знаю, является ли это стандартом для INI-файлов или нет, не я этот файл создавал.

Задача - поменять значения powerButtonAction в различных субсукциях.

Пробовал достучаться до нужного значения так (хотя бы считать):
import ConfigParser
config=ConfigParser.ConfigParser()
config.read('$fileName')

print( config.get('AC][HandleButtonEvents', 'powerButtonAction' ) )

Но возникает ошибка:
      "Traceback (most recent call last):",
      "  File \"<stdin>\", line 5, in <module>",
      "  File \"/usr/lib/python2.7/ConfigParser.py\", line 607, in get",
      "    raise NoSectionError(section)",
      "ConfigParser.NoSectionError: No section: 'AC][HandleButtonEvents'"

Вопрос: как работать с такими файлами?

UPD: При необходимости могу поставить Python 3.5.3, если это будет нужно для решения.

★★★★★

Последнее исправление: Xintrea (всего исправлений: 1)
Ответ на: комментарий от anonymous

Там что-то про вложенные секции написано: https://pypi.org/project/configobj/

Вот именно что что-то. Там написано про другие субсекции:

[ "section 1" ]
# This comment goes with keyword 3
keyword 3 = value 3
'keyword 4' = value4, value 5, 'value 6'

    [[ sub-section ]]    # an inline comment
    # sub-section is inside "section 1"
    'keyword 5' = 'value 7'
    'keyword 6' = '''A multiline value,
that spans more than one line :-)
The line breaks are included in the value.'''

        [[[ sub-sub-section ]]]
        # sub-sub-section is *in* 'sub-section'
        # which is in 'section 1'
        'keyword 7' = 'value 8'

Xintrea ★★★★★
() автор топика
Ответ на: комментарий от Xintrea

Кажется это немного нестандартный формат ini. Мб проще регулярками разделить строки на блоки. Тип ^\[\w - начало нового блока. Нужный тебе блок можно найти просто сравнив строку с образцом. Ну а внутри блока ты можешь так же ориентироваться используя регулярки или скормить один блок в ConfigParser подменив название блока на то, которое ConfigParser в состоянии переварить.

Aswed ★★★★★
()
Ответ на: комментарий от Aswed

Вроде как через sed или awk можно, нашел такое обсуждение:

https://qastack.ru/unix/188264/want-to-substitute-only-first-occurence-with-sed

Но там описываются решения с явным учетом номеров строк.

А как сделать универсально, пока непонятно.

Xintrea ★★★★★
() автор топика
Ответ на: комментарий от Aswed

Кажется это немного нестандартный формат ini. Мб проще регулярками разделить строки на блоки. Тип ^\[\w - начало нового блока.

Я создал новую тему:

Как в SED обработать диапазон строк?

Может быть, сможешь подсказать в такой постановке вопроса?

Xintrea ★★★★★
() автор топика
import re
s = """
[AC]
icon=battery-charging

[AC][DPMSControl]
idleTime=3600

[AC][HandleButtonEvents]
lidAction=64
powerButtonAction=8

[Battery]
icon=battery-060

[Battery][DPMSControl]
idleTime=300

[Battery][HandleButtonEvents]
lidAction=64
powerButtonAction=16

[LowBattery]
icon=battery-low

[LowBattery][BrightnessControl]
value=30

[LowBattery][HandleButtonEvents]
lidAction=64
powerButtonAction=16
"""


def parse(text):
    result = {}
    section_data = result
    rx_section = re.compile(r'\[.*?\]')
    rx_keyvalue = re.compile(r'^(.*?)=(.*)$')

    for line in text.splitlines():
        match = rx_section.findall(line)
        if match:
            section_data = result
            for section in match:
                section_data = section_data.setdefault(section, {})

        match = rx_keyvalue.match(line)
        if match:
            section_data[match.group(0)] = match.group(1)

    return result


pprint.pprint(parse(s))
anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.