高级过滤方法

这节内容主要介绍使用 F 对象来做高级过滤。如果你已经足够了解 F 对象的操作方法,可以直接到本节最后翻看两个新的列表过滤方法:__any__all

先从初始化 nornir 对象开始,查看现在的主机清单和组:

  1. [1]:
  1. from nornir import InitNornir
  2. from nornir.core.filter import F
  3. nr = InitNornir(config_file="advanced_filtering/config.yaml")
  1. [15]:
  1. # %load advanced_filtering/inventory/hosts.yaml
  2. ---
  3. cat:
  4. groups:
  5. - terrestrial
  6. - mammal
  7. data:
  8. domestic: true
  9. diet: omnivore
  10. additional_data:
  11. lifespan: 17
  12. famous_members:
  13. - garfield
  14. - felix
  15. - grumpy
  16. bat:
  17. groups:
  18. - terrestrial
  19. - mammal
  20. data:
  21. domestic: false
  22. fly: true
  23. diet: carnivore
  24. additional_data:
  25. lifespan: 15
  26. famous_members:
  27. - batman
  28. - count chocula
  29. - nosferatu
  30. eagle:
  31. groups:
  32. - terrestrial
  33. - bird
  34. data:
  35. domestic: false
  36. diet: carnivore
  37. additional_data:
  38. lifespan: 50
  39. famous_members:
  40. - thorondor
  41. - sam
  42. canary:
  43. groups:
  44. - terrestrial
  45. - bird
  46. data:
  47. domestic: true
  48. diet: herbivore
  49. additional_data:
  50. lifespan: 15
  51. famous_members:
  52. - tweetie
  53. caterpillaer:
  54. groups:
  55. - terrestrial
  56. - invertebrate
  57. data:
  58. domestic: false
  59. diet: herbivore
  60. additional_data:
  61. lifespan: 1
  62. famous_members:
  63. - Hookah-Smoking
  64. octopus:
  65. groups:
  66. - marine
  67. - invertebrate
  68. data:
  69. domestic: false
  70. diet: carnivore
  71. additional_data:
  72. lifespan: 1
  73. famous_members:
  74. - sharktopus
  1. [4]:
  1. # %load advanced_filtering/inventory/groups.yaml
  2. ---
  3. mammal:
  4. data:
  5. reproduction: birth
  6. fly: false
  7. bird:
  8. data:
  9. reproduction: eggs
  10. fly: true
  11. invertebrate:
  12. data:
  13. reproduction: mitosis
  14. fly: false
  15. terrestrial: {}
  16. marine: {}

在上面的主机及主机组文件中,建立了具有不同属性的动物分类。F 对象可以只需在前面加上两个下划线和魔术方法的名称即可访问每种类型的魔术方法。例如,如果想检查一个列表是否包含一个特定的元素,你可以在前面加上 __contains。现在来查找属于鸟类(bird)的所有动物:

  1. [2]:
  1. birds = nr.filter(F(groups__contains="bird"))
  2. print(birds.inventory.hosts.keys())
  3. # dict_keys(['鹰', '金丝雀'])
  1. dict_keys(['eagle', 'canary'])

还可以通过添加 ~ 来对 F对象进行取反:

  1. [3]:
  1. not_birds = nr.filter(~F(groups__contains="bird"))
  2. print(not_birds.inventory.hosts.keys())
  3. # dict_keys(['猫', '蝙蝠', '毛毛虫', '章鱼'])
  1. dict_keys(['cat', 'bat', 'caterpillaer', 'octopus'])

还可以组合 F 对象并使用符号 &| 执行 AND 和 OR 运算:

  1. [4]:
  1. # 筛选鸟类(bird)或者家养动物(domestic)
  2. domestic_or_bird = nr.filter(F(groups__contains="bird") | F(domestic=True))
  3. print(domestic_or_bird.inventory.hosts.keys())
  4. # dict_keys(['猫', '鹰', '金丝雀'])
  1. dict_keys(['cat', 'eagle', 'canary'])
  1. [5]:
  1. # 筛选哺乳动物(mammal)并且是家养动物(domestic)
  2. domestic_mammals = nr.filter(F(groups__contains="mammal") & F(domestic=True))
  3. print(domestic_mammals.inventory.hosts.keys())
  4. # dict_keys(['猫'])
  1. dict_keys(['cat'])

也可以将所有符号进行组合:

  1. [6]:
  1. # 筛选会飞的动物(fly)并且不是食肉动物(cannivore)
  2. flying_not_carnivore = nr.filter(F(fly=True) & ~F(diet="carnivore"))
  3. print(flying_not_carnivore.inventory.hosts.keys())
  4. # dict_keys(['金丝雀'])
  1. dict_keys(['canary'])

可以像访问魔法方法一样访问嵌套数据,方法是在要访问的数据前面添加双下划线;在数据筛选之后,还能继续添加双下划线来访问最终数据的魔法方法。 例如在示例数据中,筛选寿命(lifespan)最终的结果是一个整数,整数可以进行比较运算,因为它具有双下划线魔术方法,所以可以对最终的数据进行再次调用魔术方法。 来筛选一下寿命(lifespan)大于 15 的动物:

  1. [7]:
  1. long_lived = nr.filter(F(additional_data__lifespan__ge=15)) # 调用了整数的 __ge__
  2. print(long_lived.inventory.hosts.keys())
  3. # dict_keys(['猫', '蝙蝠', '鹰', '金丝雀'])
  1. dict_keys(['cat', 'bat', 'eagle', 'canary'])
  1. [8]:
  1. # 结合这个例子,增加对上一个代码框的理解
  2. # 使用整数的魔术方法进行比较大小
  3. # 定义 a = 1,b = 2
  4. a = 1
  5. b = 2
  6. # 调用 a 的 魔术方法,将 b 作为参数传入,等价于 a >= b
  7. a.__ge__(b)
  1. [8]:
  1. False

除了 __contains 外,还有两个选项可以对列表进行处理:anyallany 代表列表中的元素是 OR 的关系,满足一个条件就可以;all 代表列表中的元素是 AND 的关系,必须满足所有的条件才行:

  1. [9]:
  1. # 筛选鸟类(bird)或者无脊椎动物(invertebrates)
  2. bird_or_invertebrates = nr.filter(F(groups__any=["bird", "invertebrate"]))
  3. print(bird_or_invertebrates.inventory.hosts.keys())
  4. # dict_keys(['鹰', '金丝雀', '毛毛虫', '章鱼'])
  1. dict_keys(['eagle', 'canary', 'caterpillaer', 'octopus'])
  1. [10]:
  1. # 筛选海生动物(marine)并且是无脊椎动物(invertebrates)
  2. marine_and_invertebrates = nr.filter(F(groups__all=["marine", "invertebrate"]))
  3. print(marine_and_invertebrates.inventory.hosts.keys())
  4. # dict_keys(['章鱼'])
  1. dict_keys(['octopus'])

从示例中可以看出,如果需要对多个组进行过滤操作的话,某些情况下使用 anyall 比使用 __contains 和多级运算 &~| 更为方便。

下一节中,将以网络设备作为对象,深入了解过滤功能在网络自动化中的使用方法。


上一节 | 下一节 | 返回首页