Как я могу читать структуры данных Perl из Python?
Я часто видел, как люди используют структуры данных Perl вместо файлов конфигурации; то есть одиночный файл, содержащий только:
%config = (
'color' => 'red',
'numbers' => [5, 8],
qr/^spam/ => 'eggs'
);
Какой лучший способ преобразовать содержимое этих файлов в структуры данных, эквивалентные Python, используя чистый Python? Пока мы можем предположить, что нет реальных выражений для оценки только структурированных данных.
Ответы
Ответ 1
Не уверен, что такое вариант использования. Здесь мое предположение: вы собираетесь делать одноразовое преобразование из Perl в Python.
Perl имеет этот
%config = (
'color' => 'red',
'numbers' => [5, 8],
qr/^spam/ => 'eggs'
);
В Python это будет
config = {
'color' : 'red',
'numbers' : [5, 8],
re.compile( "^spam" ) : 'eggs'
}
Итак, я предполагаю, что это куча RE для замены
-
%variable = (
с variable = {
-
);
с }
-
variable => value
с variable : value
-
qr/.../ =>
с re.compile( r"..." ) : value
Однако встроенный dict
Python не делает ничего необычного с регулярным выражением как хэш-ключ. Для этого вам нужно будет написать свой собственный подкласс dict
и переопределить __getitem__
, чтобы отдельно проверить REGEX.
class PerlLikeDict( dict ):
pattern_type= type(re.compile(""))
def __getitem__( self, key ):
if key in self:
return super( PerlLikeDict, self ).__getitem__( key )
for k in self:
if type(k) == self.pattern_type:
if k.match(key):
return self[k]
raise KeyError( "key %r not found" % ( key, ) )
Вот пример использования Perl-подобного dict.
>>> pat= re.compile( "hi" )
>>> a = { pat : 'eggs' } # native dict, no features.
>>> x=PerlLikeDict( a )
>>> x['b']= 'c'
>>> x
{<_sre.SRE_Pattern object at 0x75250>: 'eggs', 'b': 'c'}
>>> x['b']
'c'
>>> x['ji']
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 10, in __getitem__
KeyError: "key 'ji' not found"
>>> x['hi']
'eggs'
Ответ 2
Использует ли чистый Python требование? Если нет, вы можете загрузить его в Perl и преобразовать в YAML или JSON. Затем используйте PyYAML или что-то подобное, чтобы загрузить их в Python.
Ответ 3
Я бы просто превратил структуру данных Perl во что-то еще. Не видя фактического файла, может быть какая-то дополнительная работа, которую мое решение не делает.
Если единственное, что в файле является объявлением одной переменной (так, no 1;
в конце и т.д.), может быть очень просто превратить ваш %config
в YAML:
perl -MYAML -le 'print YAML::Dump( { do shift } )' filename
do
возвращает последнее значение, которое он оценил, поэтому в этом маленьком коде он возвращает список пар хеш-ключ-значение. Такие вещи, как YAML:: Dump, любят работать со ссылками, поэтому они получают намек на структуру верхнего уровня, поэтому я делаю это в хеш-ссылке, окружая do
фигурными фигурными скобками. Для вашего примера я бы получил этот вывод YAML:
---
(?-xism:^spam): eggs
color: red
numbers:
- 5
- 8
Я не знаю, как Python понравится это строковое регулярное выражение. У вас действительно есть ключ, который является регулярным выражением? Мне было бы интересно узнать, как это используется как часть конфигурации.
Если в файле есть лишний материал, жизнь немного сложнее. Вероятно, есть очень умный способ обойти это, но я использовал ту же идею, но просто жестко закодировал имя переменной, которое я хотел.
Я пробовал это в структуре данных Perl, которую использует модуль CPAN.pm, и похоже, что это получилось отлично. Единственное уродство - это предварительное знание имени переменной, которое оно предоставляет. Теперь, когда вы видели ошибку конфигурации в коде Perl, не делайте ошибку с кодом Python.:)
YAML:
perl -MYAML -le 'do shift; print YAML::Dump( $CPAN::Config )' MyConfig.pm
JSON:
perl -MJSON::Any -le 'do shift; my $j = JSON::Any->new; print $j->objToJson( $CPAN::Config )' MyConfig.pm
или
# suggested by JF Sebastian
perl -MJSON -le 'do shift; print to_json( $CPAN::Config )' MyConfig.pm
XML:: Simple не так хорошо работает, потому что он обрабатывает все как атрибут, но, возможно, кто-то может улучшить это:
perl -MXML::Simple -le 'do shift; print XMLout( $CPAN::Config )' MyConfig.pm
Ответ 4
Я также нашел PyPerl, но он, похоже, не поддерживается. Я думаю, что-то вроде этого - то, что я искал - модуль, который сделал некоторую базовую интерпретацию Perl и передал результат как объект Python. Переводчик Perl, который умер на чем-то слишком сложном, будет в порядке.: -)