You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何hasattr无法检测yaml.safe_load加载的字典中ethernets键?

问题

我写了一段读取YAML配置文件的Python代码,需要判断配置中是否存在ethernets属性,于是用ethernets1测试属性不存在时的代码行为。测试代码如下:

#!/usr/bin/python

import yaml
import simplejson as json

NETPLAN = "/etc/netplan/01-network-manager-all.yaml"

# get netplan file
with open(NETPLAN, "r") as stream:
    try:
        netplan_config = yaml.safe_load(stream)
        print("netplan_config = " + json.dumps(netplan_config))
        stream.close()
    except yaml.YAMLError as e:
        print(f"error = {str(e)}")

# test 1
if hasattr(netplan_config["network"], "ethernets"):
    print("mark1")
else:
    print("mark2")

# test 2
if netplan_config["network"]["ethernets"]:
    print("mark3")
else:
    print("mark4")

# test 3
if netplan_config["network"]["ethernets1"]:
    print("mark5")
else:
    print("mark6")

# test 4
try:
    if netplan_config["network"]["ethernets1"]:
        print("mark7")
except KeyError:
    print("mark8")

输出结果:

mark2
mark3
error thrown: KeyError: 'ethernets1'

我不理解为什么hasattr没法作用在netplan_config上,导致mark1没被打印出来;另外test2的写法在属性不存在时会报错。我知道test4可行,但更倾向用更简洁的写法替代hasattr。

参考的YAML配置文件内容:

network:
  ethernets:
    eth0:
      addresses:
      - 192.168.4.31/22
      dhcp4: false
      dhcp6: false
      match:
        macaddress: 24:4b:fe:e2:1c:4a
      nameservers:
        addresses:
        - 8.8.8.8
        - 8.8.4.4
      routes:
      - to: default
        via: 192.168.4.1
      set-name: eth0
  renderer: NetworkManager
  version: 2

解答

问题核心在于:yaml.safe_load()加载YAML文件后返回的是Python字典对象,不是自定义类的实例,而hasattr()是用来检查对象是否有某个**属性(类的成员变量/方法)**的,不是用来检查字典是否有某个键的。

所以test1里用hasattr(netplan_config["network"], "ethernets")永远会返回False,因为字典的键不是对象的属性——字典的属性是keys()、values()这类方法,而ethernets是字典的键,不是属性。

要判断字典中是否存在某个键,正确的写法有两种:

  • 使用in关键字(最简洁直接)
    把test1改成:

    # 修正后的test1
    if "ethernets" in netplan_config["network"]:
        print("mark1")
    else:
        print("mark2")
    

    这样就能正确识别ethernets是否存在,输出mark1;如果换成ethernets1,则会输出mark2。

  • 使用字典的get()方法(适合要同时获取值的场景)
    如果需要在判断存在的同时获取对应的值,可以用get(),它在键不存在时会返回None(或你指定的默认值),不会抛出KeyError:

    ethernets_config = netplan_config["network"].get("ethernets")
    if ethernets_config:
        print("mark1")
    else:
        print("mark2")
    

另外你提到的test2写法netplan_config["network"]["ethernets"],当键不存在时会直接抛出KeyError,这是字典的默认行为——直接通过[]访问不存在的键就会报错,所以这种写法不安全,建议用上面两种方式替代。

内容的提问来源于stack exchange,提问作者xinthose

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 08:45:01