繁体   English   中英

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

[英]How can I read Perl data structures from Python?

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

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

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

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

我只是将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

不知道用例是什么。 这是我的假设:您将进行一次从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/.../ => with 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'

我也找到了PyPerl ,但是似乎没有得到维护。 我猜想我正在寻找这样的东西-一个对Perl进行了一些基本解释并将结果作为Python对象传递的模块。 如果Perl解释器死于任何过于复杂的情况,那就很好了。 :-)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM