Какой формат файла конфигурации использовать для удобных строк произвольных байтов?

Поэтому я сделал короткий скрипт Python для запуска файлов в Windows с неоднозначными расширениями, изучив их магическое число / подпись файла сначала:

Я хотел бы скомпилировать его в .exe, чтобы упростить ассоциацию (либо с использованием bbfreeze, либо с перезаписью на C), но мне нужен какой-то удобный для пользователя файл конфигурации, чтобы указать соответствующие строки байтов и пути к программе. В основном я хочу как-то поместить эту информацию в простой текстовый файл:

magic_numbers = {
# TINA
'OBSS': r'%PROGRAMFILES(X86)%\DesignSoft\Tina 9 - TI\TINA.EXE',

# PSpice
'*version': r'%PROGRAMFILES(X86)%\Orcad\Capture\Capture.exe', 
'x100\x88\xce\xcf\xcfOrCAD ': '', #PSpice?

# Protel
'DProtel': r'%PROGRAMFILES(X86)%\Altium Designer S09 Viewer\dxp.exe', 

# Eagle
'\x10\x80': r'%PROGRAMFILES(X86)%\EAGLE-5.11.0\bin\eagle.exe',
'\x10\x00': r'%PROGRAMFILES(X86)%\EAGLE-5.11.0\bin\eagle.exe',
'<?xml version="1.0" encoding="utf-8"?>\n<!DOCTYPE eagle ': r'%PROGRAMFILES(X86)%\EAGLE-5.11.0\bin\eagle.exe',

# PADS Logic
'\x00\xFE': r'C:\MentorGraphics\9.3PADS\SDD_HOME\Programs\powerlogic.exe', 
}

(Шестнадцатеричные байты - это просто произвольные байты, а не символы Юникода.)

Я предполагаю, что файл .py в этом формате работает, но я должен оставить его некомпилированным и каким-то образом все еще импортировать его в скомпилированный файл, и все еще есть куча постороннего контента, такого как { и ,, который / облажался.

Я посмотрел на YAML, и это было бы здорово, за исключением того, что для этого сначала требуются двоичные файлы с кодировкой base64, что на самом деле не то, что я хочу. Я бы предпочел, чтобы конфигурационный файл содержал шестнадцатеричные представления байтов. Но также и представления ASCII, если это все, что есть в подписи файла. И, возможно, также регулярные выражения. : D (Например, если формат на основе XML может быть записан с разным количеством пробелов)

Любые идеи?


person endolith    schedule 13.03.2012    source источник
comment
Вы смотрели python-magic?   -  person jterrace    schedule 13.03.2012
comment
@jterrace: Нет, но 1. Это, наверное, излишество, если вы имеете дело только с одним расширением файла? 2. Возможно, libmagic все равно не распознает нужные мне форматы? Однако их формат файла кажется актуальным. Я не понимал, что они тоже обрабатывают регулярные выражения.   -  person endolith    schedule 13.03.2012
comment
Что хорошо в libmagic, так это то, что вы можете добавлять свои собственные пользовательские форматы, чтобы вы могли легко расширять их своими   -  person jterrace    schedule 13.03.2012
comment
@jterrace: Да, подтверждено, что команда file просто говорит, что это данные и не не знаю больше, чем это. Можно добавлять собственные форматы, но тогда я просто выполняю то же самое, что уже сделал.   -  person endolith    schedule 13.03.2012
comment
Да, я думаю, что я бы разделил два файла конфигурации: один для связывания магических чисел с mimetypes, а другой для связывания mimetypes с путями запуска.   -  person jterrace    schedule 13.03.2012
comment
@jterrace: У этих файлов есть даже миметики?   -  person endolith    schedule 13.03.2012
comment
Это то, что вам дает libmagic. Если в файлах нет официальных типов мин, люди обычно просто придумывают один   -  person jterrace    schedule 13.03.2012
comment
@jterrace: Можете ли вы предложить это в качестве ответа?   -  person endolith    schedule 13.03.2012


Ответы (3)


Вы уже получили ответ: YAML.

Данные, которые вы разместили выше, хранят текстовые представления двоичных данных; это будет хорошо для YAML, вам просто нужно правильно его проанализировать. Обычно вы используете что-то из модуля binascii; в данном случае, скорее всего, функция binascii.a2b_qp.

magic_id_str = 'x100\x88\xce\xcf\xcfOrCAD '
magic_id = binascii.a2b_qp(magic_id_str)

Чтобы пояснить, я буду использовать символ Юникода как простой способ вставить двоичные данные в REPL (Python 2.7):

>>> a = 'Φ'  
>>> a  
'\xce\xa6'  
>>> binascii.b2a_qp(a)  
'=CE=A6'  
>>> magic_text = yaml.load("""  
... magic_string: '=CE=A6'  
... """)  
>>> magic_text  
{'magic_string': '=CE=A6'}  
>>> binascii.a2b_qp(magic_text['magic_string'])  
'\xce\xa6'  
person Peter V    schedule 13.03.2012
comment
Подождите, а как бы вы записали это в файл конфигурации и использовали его с yaml.load? Теперь я думаю, что формат может быть немного более сложным, со спецификатором для типа данных, и вы можете ввести что-то вроде [string, DProtel] или [hex, 88 ce cf cf], и программа будет обрабатывать каждый по-разному. - person endolith; 13.03.2012
comment
Теперь у меня это работает неявно с yaml.add_implicit_resolver. Все, что находится в форме 88 ce cf c4, преобразуется в двоичную форму, теги не требуются. Все остальное интерпретируется как строка. - person endolith; 14.03.2012

Я бы посоветовал сделать это немного по-другому. Я бы отделил эти две настройки друг от друга:

  1. Подпись магического числа ===> mimetype
  2. mimetype ==> программа запуска

Для первой части я бы использовал python-magic, библиотеку, которая привязана к libmagic. Вы можете заставить python-magic использовать собственный волшебный файл, например:

import magic
m = magic.Magic(magic_file='/path/to/magic.file')

Ваши пользователи могут указать настраиваемый магический файл, отображающий магические числа в миметипы. Синтаксис волшебных файлов задокументирован. Вот пример, показывающий волшебный файл для формата TIFF:

# Tag Image File Format, from Daniel Quinlan ([email protected])
# The second word of TIFF files is the TIFF version number, 42, which has
# never changed.  The TIFF specification recommends testing for it.
0       string          MM\x00\x2a      TIFF image data, big-endian
!:mime  image/tiff
0       string          II\x2a\x00      TIFF image data, little-endian
!:mime  image/tiff

Вторая часть довольно проста, так как теперь вам нужно указать только текстовые данные. Вы можете использовать формат INI или yaml, как предлагали другие, или даже иметь простой файл с разделителями-табуляторами, например:

image/tiff         C:\Program Files\imageviewer.exe
application/json   C:\Program Files\notepad.exe
person jterrace    schedule 13.03.2012

Я использовал несколько пакетов для создания файлов конфигурации, в том числе yaml. Я рекомендую вам использовать ConfigParser или ConfigObj.

Наконец, лучший вариант. Если вы хотите создать удобочитаемый файл конфигурации с комментариями, я настоятельно рекомендую использовать ConfigObj.

Наслаждаться!

Пример ConfigObj

С помощью этого кода:

Вы также можете использовать ConfigObj для их хранения. Попробуйте это: импортировать configobj

def createConfig(path):
    config = configobj.ConfigObj()
    config.filename = path
    config["Sony"] = {}
    config["Sony"]["product"] = "Sony PS3"
    config["Sony"]["accessories"] = ['controller', 'eye', 'memory stick']
    config["Sony"]["retail price"] = "$400"
    config["Sony"]["binary one"]= bin(173)
    config.write()

Вы получите этот файл:

[Sony]
product = Sony PS3
accessories = controller, eye, memory stick
retail price = $400
binary one = 0b10101101
person carlesh    schedule 13.03.2012
comment
Нет упоминания о том, как представлять двоичные значения? - person endolith; 13.03.2012
comment
Цель состоит в том, чтобы вручную писать файлы конфигурации и читать их программному обеспечению, а не наоборот. - person endolith; 13.03.2012
comment
Файлы INI обычно ограничены двумя уровнями (разделы и свойства) и плохо обрабатывают двоичные данные. - person endolith; 13.03.2012