如何从Python中读取Perl数据结构?
我经常看到人们用Perl数据结构代替配置文件;i、 e.仅包含以下内容的单独文件:如何从Python中读取Perl数据结构?,python,perl,configuration,data-structures,Python,Perl,Configuration,Data Structures,我经常看到人们用Perl数据结构代替配置文件;i、 e.仅包含以下内容的单独文件: %config = ( 'color' => 'red', 'numbers' => [5, 8], qr/^spam/ => 'eggs' ); 使用纯Python将这些文件的内容转换为与Python等效的数据结构的最佳方法是什么?目前,我们可以假设没有真正的表达式需要计算,只有结构化数据。使用纯Python是一种要求吗?如果没有,您可以在Perl中加载它并将其转换为
%config = (
'color' => 'red',
'numbers' => [5, 8],
qr/^spam/ => 'eggs'
);
使用纯Python将这些文件的内容转换为与Python等效的数据结构的最佳方法是什么?目前,我们可以假设没有真正的表达式需要计算,只有结构化数据。使用纯Python是一种要求吗?如果没有,您可以在Perl中加载它并将其转换为YAML或JSON。然后使用PyYAML或类似的东西在Python中加载它们。不确定用例是什么。这里是我的假设:您将执行从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=>value
变量:value
带qr/../=>
re.compile(r“…”):值
regex作为散列键并没有做任何不寻常的事情。为此,您必须编写自己的dict
子类,并重写\uu getitem\uuuu
以分别检查正则表达式键
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'
pat=re.compile(“hi”)
>>>a={pat:'eggs'}#本机dict,无特征。
>>>x=PerlLikeDict(a)
>>>x['b']='c'
>>>x
{:‘蛋’,‘b’:‘c’}
>>>x['b']
“c”
>>>x['ji']
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“”,第10行,在\uu getitem中__
KeyError:“找不到键'ji'”
>>>x['hi']
“鸡蛋”
我也找到了,但它似乎没有得到维护。我想这就是我想要的——一个对Perl做了一些基本解释并将结果作为Python对象传递的模块。如果一个Perl解释器在任何过于复杂的情况下都会失效,那就好了。:-) 我只想将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
JSON:
或
XML::Simple的效果不太好,因为它将所有内容都视为一个属性,但也许有人可以对此进行改进:
perl -MXML::Simple -le 'do shift; print XMLout( $CPAN::Config )' MyConfig.pm
我想使用纯Python,但这还是很有帮助的。:)当数据结构被嵌套时,它可能会变得更复杂,这可能需要某种递归解析器。如果它变得更复杂,我们就必须更详细地了解用例。这种东西看起来像是一次性的手工转化。但也许不是。无法从问题中分辨出实际用例是什么。这一总体思路需要一些小的调整。(正则表达式转换有点棘手。)(正则表达式转换的意思是正则表达式被用作散列中的键——将它们更改为re.compile形式是非常重要的。)“正则表达式被用作散列中的键”这意味着什么?PyPerl不是纯Python。这是一个用C编写的python扩展模块。要点是——我想我在寻找类似PyPerl的东西,它是用纯python实现的。:-)对于OP myconfig.pm,它可以是
perl-MJSON-E'do shift;对_json\%config'myconfig.pm
。但是Python不会理解“(?-xism:^spam)”regexp。这是一个非常好的解决方案。试图从perl之外的任何东西中快速解析perl都需要大量的工作。你甚至可以用python将整个过程包装在函数调用中,它只是一个subprocess.Popen和json.load调用。。。有风险的请确保您知道这是应用程序的最佳方式,而且Yaml、XML或平面文件等东西没有比这更好的东西。对,我不建议任何人选择这样做——这是我继承的东西。:-)琐事:Perl本机不支持这一点。所有哈希键都是字符串化的;在Perl中,除了字符串之外,不可能对哈希键使用任何东西。您必须使用类似于模块的方法来解析这样的散列工作,而且由于Perl积极地扰乱散列键-值对的顺序,因此这样一个命令的输出可能定义得很差。如果您的配置文件必须是可执行的,那么您最好编写一个适当的perl模块,其中包含一个子模块和一堆如果$url=~qr/^spam/,则返回“鸡蛋”代码>行。。。
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
perl -MXML::Simple -le 'do shift; print XMLout( $CPAN::Config )' MyConfig.pm