我经常看到人们使用Perl数据结构代替配置文件;即仅包含以下内容的单独文件:
%config = (
'color' => 'red',
'numbers' => [5, 8],
qr/^spam/ => 'eggs'
);
使用纯Python将这些文件的内容转换为Python等效数据结构的最佳方法是什么?暂时我们可以假设没有真正的表达式来评估,只有结构化数据。
答案 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 => value
与variable : 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翻译死于任何太复杂的事情都没关系。 : - )