Search code examples
pythonperlconfigurationdata-structures

How can I read Perl data structures from Python?


I've often seen people use Perl data structures in lieu of configuration files; i.e. a lone file containing only:

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

What's the best way to convert the contents of these files into Python-equivalent data structures, using pure Python? For the time being we can assume that there are no real expressions to evaluate, only structured data.


Solution

  • Not sure what the use case is. Here's my assumption: you're going to do a one-time conversion from Perl to Python.

    Perl has this

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

    In Python, it would be

    config = {
        'color' : 'red',
        'numbers' : [5, 8],
        re.compile( "^spam" ) : 'eggs'
    }
    

    So, I'm guessing it's a bunch of RE's to replace

    • %variable = ( with variable = {
    • ); with }
    • variable => value with variable : value
    • qr/.../ => with re.compile( r"..." ) : value

    However, Python's built-in dict doesn't do anything unusual with a regex as a hash key. For that, you'd have to write your own subclass of dict, and override __getitem__ to check REGEX keys separately.

    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, ) )
    

    Here's the example of using a Perl-like 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'