高级过滤方法

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

    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. - terrestrial
    44. - bird
    45. data:
    46. diet: herbivore
    47. additional_data:
    48. lifespan: 15
    49. famous_members:
    50. - tweetie
    51. caterpillaer:
    52. groups:
    53. - terrestrial
    54. - invertebrate
    55. data:
    56. domestic: false
    57. diet: herbivore
    58. additional_data:
    59. lifespan: 1
    60. famous_members:
    61. - Hookah-Smoking
    62. octopus:
    63. groups:
    64. - marine
    65. - invertebrate
    66. data:
    67. domestic: false
    68. diet: carnivore
    69. additional_data:
    70. lifespan: 1
    71. famous_members:
    72. - 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'])
    1. [3]:
    1. not_birds = nr.filter(~F(groups__contains="bird"))
    2. print(not_birds.inventory.hosts.keys())
    3. # dict_keys(['猫', '蝙蝠', '毛毛虫', '章鱼'])

    还可以组合 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'])
    1. [7]:
    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. # dict_keys(['章鱼'])

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


    上一节 | | 返回首页