高级过滤方法
这节内容主要介绍使用 F
对象来做高级过滤。如果你已经足够了解 F
对象的操作方法,可以直接到本节最后翻看两个新的列表过滤方法:__any
和 __all
。
先从初始化 nornir
对象开始,查看现在的主机清单和组:
[1]:
from nornir import InitNornir
from nornir.core.filter import F
nr = InitNornir(config_file="advanced_filtering/config.yaml")
[15]:
# %load advanced_filtering/inventory/hosts.yaml
---
cat:
groups:
- terrestrial
- mammal
data:
domestic: true
diet: omnivore
additional_data:
lifespan: 17
famous_members:
- garfield
- felix
- grumpy
bat:
groups:
- terrestrial
- mammal
data:
domestic: false
fly: true
diet: carnivore
additional_data:
lifespan: 15
famous_members:
- batman
- count chocula
- nosferatu
eagle:
groups:
- terrestrial
- bird
data:
domestic: false
diet: carnivore
additional_data:
lifespan: 50
famous_members:
- thorondor
- sam
canary:
groups:
- terrestrial
- bird
data:
domestic: true
diet: herbivore
additional_data:
lifespan: 15
famous_members:
- tweetie
caterpillaer:
groups:
- terrestrial
- invertebrate
data:
domestic: false
diet: herbivore
additional_data:
lifespan: 1
famous_members:
- Hookah-Smoking
octopus:
groups:
- marine
- invertebrate
data:
domestic: false
diet: carnivore
additional_data:
lifespan: 1
famous_members:
- sharktopus
[4]:
# %load advanced_filtering/inventory/groups.yaml
---
mammal:
data:
reproduction: birth
fly: false
bird:
data:
reproduction: eggs
fly: true
invertebrate:
data:
reproduction: mitosis
fly: false
terrestrial: {}
marine: {}
在上面的主机及主机组文件中,建立了具有不同属性的动物分类。F
对象可以只需在前面加上两个下划线和魔术方法的名称即可访问每种类型的魔术方法。例如,如果想检查一个列表是否包含一个特定的元素,你可以在前面加上 __contains
。现在来查找属于鸟类(bird
)的所有动物:
[2]:
birds = nr.filter(F(groups__contains="bird"))
print(birds.inventory.hosts.keys())
# dict_keys(['鹰', '金丝雀'])
dict_keys(['eagle', 'canary'])
还可以通过添加 ~
来对 F
对象进行取反:
[3]:
not_birds = nr.filter(~F(groups__contains="bird"))
print(not_birds.inventory.hosts.keys())
# dict_keys(['猫', '蝙蝠', '毛毛虫', '章鱼'])
dict_keys(['cat', 'bat', 'caterpillaer', 'octopus'])
还可以组合 F
对象并使用符号 &
和 |
执行 AND 和 OR 运算:
[4]:
# 筛选鸟类(bird)或者家养动物(domestic)
domestic_or_bird = nr.filter(F(groups__contains="bird") | F(domestic=True))
print(domestic_or_bird.inventory.hosts.keys())
# dict_keys(['猫', '鹰', '金丝雀'])
dict_keys(['cat', 'eagle', 'canary'])
[5]:
# 筛选哺乳动物(mammal)并且是家养动物(domestic)
domestic_mammals = nr.filter(F(groups__contains="mammal") & F(domestic=True))
print(domestic_mammals.inventory.hosts.keys())
# dict_keys(['猫'])
dict_keys(['cat'])
也可以将所有符号进行组合:
[6]:
# 筛选会飞的动物(fly)并且不是食肉动物(cannivore)
flying_not_carnivore = nr.filter(F(fly=True) & ~F(diet="carnivore"))
print(flying_not_carnivore.inventory.hosts.keys())
# dict_keys(['金丝雀'])
dict_keys(['canary'])
可以像访问魔法方法一样访问嵌套数据,方法是在要访问的数据前面添加双下划线;在数据筛选之后,还能继续添加双下划线来访问最终数据的魔法方法。 例如在示例数据中,筛选寿命(lifespan)最终的结果是一个整数,整数可以进行比较运算,因为它具有双下划线魔术方法,所以可以对最终的数据进行再次调用魔术方法。 来筛选一下寿命(lifespan)大于 15 的动物:
[7]:
long_lived = nr.filter(F(additional_data__lifespan__ge=15)) # 调用了整数的 __ge__
print(long_lived.inventory.hosts.keys())
# dict_keys(['猫', '蝙蝠', '鹰', '金丝雀'])
dict_keys(['cat', 'bat', 'eagle', 'canary'])
[8]:
# 结合这个例子,增加对上一个代码框的理解
# 使用整数的魔术方法进行比较大小
# 定义 a = 1,b = 2
a = 1
b = 2
# 调用 a 的 魔术方法,将 b 作为参数传入,等价于 a >= b
a.__ge__(b)
[8]:
False
除了 __contains
外,还有两个选项可以对列表进行处理:any
和 all
。 any
代表列表中的元素是 OR 的关系,满足一个条件就可以;all
代表列表中的元素是 AND 的关系,必须满足所有的条件才行:
[9]:
# 筛选鸟类(bird)或者无脊椎动物(invertebrates)
bird_or_invertebrates = nr.filter(F(groups__any=["bird", "invertebrate"]))
print(bird_or_invertebrates.inventory.hosts.keys())
# dict_keys(['鹰', '金丝雀', '毛毛虫', '章鱼'])
dict_keys(['eagle', 'canary', 'caterpillaer', 'octopus'])
[10]:
# 筛选海生动物(marine)并且是无脊椎动物(invertebrates)
marine_and_invertebrates = nr.filter(F(groups__all=["marine", "invertebrate"]))
print(marine_and_invertebrates.inventory.hosts.keys())
# dict_keys(['章鱼'])
dict_keys(['octopus'])
从示例中可以看出,如果需要对多个组进行过滤操作的话,某些情况下使用 any
和 all
比使用 __contains
和多级运算 &
、~
、|
更为方便。
下一节中,将以网络设备作为对象,深入了解过滤功能在网络自动化中的使用方法。