如何从Python中读取Perl数据结构?

时间:2008-12-23 20:11:08

标签: python perl configuration data-structures

我经常看到人们使用Perl数据结构代替配置文件;即仅包含以下内容的单独文件:

%config = (
    'color' => 'red',
    'numbers' => [5, 8],
    qr/^spam/ => 'eggs'
);

使用纯Python将这些文件的内容转换为Python等效数据结构的最佳方法是什么?暂时我们可以假设没有真正的表达式来评估,只有结构化数据。

4 个答案:

答案 0 :(得分:18)

使用纯Python是一项要求吗?如果没有,您可以在Perl中加载它并将其转换为YAML或JSON。然后使用PyYAML或类似的东西在Python中加载它们。

答案 1 :(得分:14)

我只是将Perl数据结构转换为其他内容。没有看到实际的文件,我的解决方案可能会有一些额外的工作。

如果文件中唯一的东西是一个变量声明(那么,最后没有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会如何使用字符串化的正则表达式。你真的有一把正则表达式的钥匙吗?我很想知道如何将其用作配置的一部分。


如果文件中有额外的东西,生活会更加艰难。可能有一种非常聪明的方法来解决这个问题,但我使用了同样的想法,但只是对我想要的变量名称进行了硬编码。

我在CPAN.pm模块使用的Perl数据结构上尝试了这个,看起来它很好。唯一的丑陋是它提供的变量名称的前瞻性知识。现在您已经在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

答案 2 :(得分:7)

不确定用例是什么。这是我的假设:你将进行从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 => valuevariable : value
  • qr/.../ =>re.compile( r"..." ) : value

然而,Python的内置dict在将正则表达式作为哈希键时没有做任何异常。为此,您必须编写自己的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的词典的例子。

>>> 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'

答案 3 :(得分:0)

我也找到PyPerl,但似乎没有保留。我想这就是我想要的东西 - 一个对Perl做了一些基本解释并将结果作为Python对象传递的模块。一个Perl翻译死于任何太复杂的事情都没关系。 : - )