我经常看到人们使用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' }
所以,我猜这是一堆替代品
%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 "", line 1, in File " ", line 10, in __getitem__ KeyError: "key 'ji' not found" >>> x['hi'] 'eggs'