在YAML格式的文件test.yaml中,某些MAC地址将被判断为数字

时间:2018-10-10 03:35:05

标签: python yaml

[80:41:26:53:24:11]的MAC地址已判断为编号62745168251  但是[84:19:14:15:86:58]已被判断为字符串 enter image description here

enter image description here

3 个答案:

答案 0 :(得分:3)

您应该始终在以数字开头并且由数字和非数字字符组成的字符串文字周围使用引号,以避免YAML解析器造成混淆:

MAC1: "80:41:26:53:24:11"

否则,如果您的字符串文字包含一系列用冒号分隔的一两位数字,而除第一个以外的所有数字都位于059之间,则它将被解释为{ {3}}数字,并将转换为等效的秒数。例如,您的MAC地址80:41:26:53:24:11将被视为十六进制数字,并转换为:

(((((80*60)+41)*60+26)*60+53)*60+24)*60+11

等于62745168251

由于您的其他MAC地址84:19:14:15:86:58在第一个超过59(即86)的数字之后有一个数字,因此它不被视为十六进制数字,并且因此,从字面上将其视为字符串。

相关的源代码可以在sexagesimalint resolver中找到。

答案 1 :(得分:2)

您没有明确声明,而是使用yaml.load()和 得到那个结果,我猜你是在用PyYAML。 您 不应使用PyYAML yaml.load(),因为这可能不安全 完全没有必要。如果您需要坚持使用PyYAML,请使用 改为yaml.safe_load()

在最新版本的YAML中((2009年发布的1.2版)core schema很重要 因为int具有changed 以前的版本(2005年的1.1)。最明显的区别是 077在YAML 1.2中不再是八进制的(使用0o77),并且 sexagesimals,在YAML中 1.1验证规则指示的文档:

|[-+]?[1-9][0-9_]*(:[0-5]?[0-9])+ # (base 60)

在YAML 1.2(不再明确和YAML 1.2中不再受支持)中 规范指向1.1语言独立类型,但是 示例已从文档中删除。)

在YAML 1.1文档中,六性的显式示例 整数are 190:20:30resp. 3:25:45。¹ 是一个整数,后跟两个组(两位)和所有 由两个冒号(:)隔开,可以用来表示 例如小时,分钟和秒。规则(正则表达式)没有限制 在+末尾的(:[0-5]?[0-9])+这些集合中只有两个 表示至少一次且没有限制。 以十六进制形式,在冒号之间,您可以使用0-9中的一位数字或 一个两位数的数字,其中第一个数字限制为0-5

PyYAML为documented,具有 YAML 1.1解析器(因此,尽管出现了YAML 1.2,但尚未更新 在2009年)。如果它们的MAC地址是六进制的,它将被读取 符合规则,大致来说,当 冒号或最后一个冒号后的字符数小于60 ,这两个键的值都一样 的值中的MAC1MAC2(值相同) NETWORK2。其他MAC地址中有:86:,不是六十进制数字。

如果您要使用PyYAML从字符串中转储这些MAC地址,它将在为您提供引号时 必要的:

import sys
import yaml

d = dict(mac1='84:19:14:15:86:58', mac2='80:41:26:53:24:11')
yaml.safe_dump(d, sys.stdout)

转储:

{mac1: '84:19:14:15:86:58', mac2: '80:41:26:53:24:11'}

请注意,我没有故意print(safe_dump(d)),这是 速度较慢(因为它必须先创建并填充内部缓冲区, 检索并输出内容)。它还增加了一个额外的空 输出末尾的换行符。

您当然可以引用所有(或所有必要的)MAC地址,但是 更简单的方法是升级到ruamel.yaml之类的YAML 1.2解析器 软件包(免责声明:我是该软件包的作者)。假设 您的输入在network.yaml中,可以使用:

import sys
import ruamel.yaml as yaml

with open('network.yaml') as fp:
    data = yaml.safe_load(fp)
print(data)

给出:

{'NETWORK1': {'BOND_MODE': 4, 'BOND_NAME': 'bond0', 'MAC1': '84:19:14:15:86:58', 'MAC2': '84:19:14:15:86:59'}, 'NETWORK2': {'BOND_MODE': 1, 'BOND_NAME': 'bond0', 'BLAN_ID': 820, 'MAC1': '80:41:26:53:24:11', 'MAC2': '80:41:26:53:24:11'}}

在往返模式下,使用较新的API,ruamel.yaml在以下情况下不会插入引号 转储,因为它们对于YAML 1.2是不必要的:

import sys
import ruamel.yaml
from pathlib import Path

network_file = Path('network.yaml')

yaml = ruamel.yaml.YAML()
# yaml.indent(mapping=4, sequence=4, offset=2)
# yaml.preserve_quotes = True
data = yaml.load(network_file)
yaml.dump(data, sys.stdout)

对于结果:

NETWORK1:
  BOND_MODE: 4
  BOND_NAME: bond0
  MAC1: 84:19:14:15:86:58
  MAC2: 84:19:14:15:86:59

NETWORK2:
  BOND_MODE: 1
  BOND_NAME: bond0
  BLAN_ID: 820
  MAC1: 80:41:26:53:24:11
  MAC2: 80:41:26:53:24:11

¹您还可以使用六进制浮点数:20:30.15

答案 2 :(得分:0)

不确定语法高亮显示了什么,但是也许有一个线索。在MAC地址之前 删除某些白点是否有区别?

如果您希望将yaml中的任何值显式评估为字符串,请将这些值用双引号或单引号引起来。