需要逻辑通过读取输入fi来创建dict的dict

2024-09-29 21:25:56 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个配置文件,其中包含以下行:

router1 = { 
   hostname: abcd 
      interfaces:{ 
          interface: gigabit 0/1 
          valn: 100 
          name: vlan1
          ip_address: 1.1.1.1 
       } 
   clear: clear config all          
  } 

我的脚本应该从配置文件中读取,并以相同的格式创建一个字典字典。基于这本词典,我可以继续我的自动化工作。你知道吗


Tags: nameipconfig字典address配置文件interfacesinterface
3条回答

这个pyparsing代码将把您的配置条目解析成一个映射,您可以像dict或object那样使用它:

from pyparsing import *

LBRACE,RBRACE,LBRACK,RBRACK,COLON,EQ = map(Suppress, "{}[]:=")
NL = LineEnd()

key = Word(alphas, alphanums+'_')
# forward declare value, since this will be a recursive definition
value = Forward()
key_value = Group(key + COLON + value)

# parse actions will do string->int and string->float conversions at parse time
integer = Regex(r'[+-]?\d+').setParseAction(lambda t: int(t[0]))
real = Regex(r'[+-]?\d+\.\d*').setParseAction(lambda t: float(t[0]))
string = restOfLine.setParseAction(lambda t: t[0].strip())

dictvalue = Group(LBRACE + Dict(ZeroOrMore(key_value)) + RBRACE)
listvalue = Group(LBRACK + Dict(ZeroOrMore(value)) + RBRACK)

# assign recursive contents to value using <<=
value <<= (real | integer) + FollowedBy(NL) | dictvalue | listvalue | string

setting = Group(key + EQ + value)

config_parser = Dict(OneOrMore(setting))

config = config_parser.parseString(data)

# dump out parsed contents
print config.dump()

# access parsed contents like a dict or an object
print config.keys()
print config.router1.keys()
print config.router1.hostname

印刷品:

[['router1', [['hostname', 'abcd '], ['interfaces', [['interface', ...
- router1: [['hostname', 'abcd '], ['interfaces', [['interface', ...
  - clear: clear config all          
  - hostname: abcd 
  - interfaces: [['interface', 'gigabit 0/1 '], ['valn', 100], ...
    - interface: gigabit 0/1 
    - ip_address: 1.1.1.1 
    - name: vlan1
    - valn: 100
['router1']
['interfaces', 'hostname', 'clear']
abcd 

请注意,作为解析过程的一部分,那些有效float或int值已经从字符串转换而来。你知道吗

要解决你的问题,你需要一个parser。在Python中有各种各样的库可用于解析,请参见sobatchelder的Python parsing tools,以获得可用的库的列表。你知道吗

但是,您的数据格式并不太复杂,因此编写一个不依赖任何第三方模块的简单解析器非常容易。要将数据分解为单独的标记(akalexical analysis),我们可以使用标准的shlex模块。你知道吗

下面的代码实现了一个非常简单的递归解析器。它是在Python2.6.6上开发和测试的,但是它应该在Python3上正常工作。您可能希望通过将其放入类中来封装它。我想这可能不是真的必要,但我想这取决于你的实际用例。你知道吗

这段代码使用json模块打印已解析的字典;这不是严格必要的,但它确实可以很容易地打印嵌套的字典。你知道吗

代码包含了一些错误检查,但是很容易被愚弄到接受奇怪的数据,因此如果不能保证输入数据总是正确的,您可能希望增强错误检查。你知道吗

#!/usr/bin/env python

''' Parse config file data; see below for example data format
    See http://stackoverflow.com/q/34898816/4014959
    Written by PM 2Ring 2016.01.21
'''

from __future__ import print_function
import shlex
import string
import json

data = '''
router1 = {
    hostname: abcd
        interfaces:{
            interface: gigabit 0/1
            valn: 100
            name: vlan1
            ip_address: 1.1.1.1
        }
    clear: clear config all
}
'''

#Set up a simple lexer. `data` must be a file-/stream-like object
# with read() and readline() methods, or a string 
lex = shlex.shlex(data)
lex.wordchars = string.ascii_letters + string.digits + "./:_"

def t_is(ch):
    ''' verify that the next token is ch '''
    token = next(lex)
    if token != ch:
        raise ValueError('Line %d: Expected %r got %r' 
            % (lex.lineno, ch, token))

def get_word():
    ''' get next token if it's a word.
        Otherwise, push it back & return None
    '''
    token = next(lex)
    if token not in '{}':
        return token
    lex.push_token(token)

def is_key(token):
    return token[-1] == ':'

def get_value():
    ''' get value, which may be a list of words or a dict '''
    token = next(lex)
    if token == '{':
        #Value is a dict
        lex.push_token(token)
        return get_dict()

    #Value consists of one or more non-key words
    value = [token]
    while True:
        token = get_word()
        if token is None:
            break
        if is_key(token):
            lex.push_token(token)
            break
        value.append(token)
    return ' '.join(value)

def get_dict():
    ''' parse a dictionary '''
    t_is('{')
    d = {}
    while True:
        #get key, value pairs
        key = get_word()
        if key is None:
            t_is('}')
            return d
        if not is_key(key):
            raise ValueError('Line %d: Bad key %r' 
                % (lex.lineno, key))
        d[key[:-1]] = get_value()

def get_cfg():
    ''' parse config data, returning the name and the dict '''
    name = get_word()
    if name is None:
        raise ValueError('Line %d: Expected name, got %r' 
            % (lex.lineno, next(lex)))
    t_is('=')
    d = get_dict()
    return name, d

#                             

print(data)
print(20 * '- ' + '\n')
#for token in lex: print(token)

name, cfg = get_cfg()
print(name)
print(json.dumps(cfg, indent=4, sort_keys=True))

输出

router1 = {
    hostname: abcd
        interfaces:{
            interface: gigabit 0/1
            valn: 100
            name: vlan1
            ip_address: 1.1.1.1
        }
    clear: clear config all
}

- - - - - - - - - - - - - - - - - - - - 

router1
{
    "clear": "clear config all", 
    "hostname": "abcd", 
    "interfaces": {
        "interface": "gigabit 0/1", 
        "ip_address": "1.1.1.1", 
        "name": "vlan1", 
        "valn": "100"
    }
}

我不知道你为什么要这么做,但我可以建议你使用JSON吗?你知道吗

试试这个,把你的文档(字典)保存为一个有效的.json文件,然后在python中这样做

import json
with open("filename.json",'r') as f:
    data=json.load(f)
print(data)

数据变量应具有与存储的数据结构相同的数据结构。如果你想要更复杂的东西,比如保存对象,试试pickle

https://docs.python.org/3/library/pickle.html

相关问题 更多 >

    热门问题