python字典内容添加到列表

append实际是添加了对象引用

python脚本计算处理器延迟

def get_cpu_frequency_msg():
    cpu_frequency_data_output = []
    cpu_frequency_data = {}
    cpu_frequency_msg = []
    cpu_frequency_data_output = subprocess.check_output("sudo cpupower monitor -m Mperf | grep -Ev 'Mperf|CPU' | awk -F\| '{print $3\" \"$6}'", shell=True).splitlines()
    for items in cpu_frequency_data_output:
        cpu_frequency_data["name"], cpu_frequency_data["value"] = "cpu"+items.split()[0], int(items.split()[1])
        print cpu_frequency_data
        cpu_frequency_msg.append(cpu_frequency_data)
        print cpu_frequency_msg

    return cpu_frequency_msg

上述脚本目的是计算出每个cpu的主频:

sudo cpupower monitor -m Mperf | grep -Ev 'Mperf|CPU' | awk -F\| '{print $3" "$6}'

命令输出是内容如下

   0   2493
  32   2494
   1   2496
  33   2493
  ...

将命令输出一行行读取到字典cpu_frequency_data,然后将字典值添加到列表cpu_frequency_msg,预期输出类似

但是,没有想到,虽然print cpu_frequency_data是正确输出了预想中的命令的每行输出,但是appendcpu_frequency_msg后,发现下一个值覆盖了上一个值,输出的cpu_frequency_msg实际是

{'name': 'cpu0', 'value': 2493}
[{'name': 'cpu0', 'value': 2493}]
{'name': 'cpu32', 'value': 2493}
[{'name': 'cpu32', 'value': 2493}, {'name': 'cpu32', 'value': 2493}]
{'name': 'cpu1', 'value': 2493}
[{'name': 'cpu1', 'value': 2493}, {'name': 'cpu1', 'value': 2493}, {'name': 'cpu1', 'value': 2493}]
{'name': 'cpu33', 'value': 2494}
[{'name': 'cpu33', 'value': 2494}, {'name': 'cpu33', 'value': 2494}, {'name': 'cpu33', 'value': 2494}, {'name': 'cpu33', 'value': 2494}]
...

可以看到,实际上每次字典cpu_frequency_dataappend到列表cpu_frequency_msg都是一个对象引用,所以导致了当cpu_frequency_msg内容变化时,列表中所有引用值同时变化。相当于最后输出的就只有最后一行采样值。

append对象的内容

要将字典内容复制给列表,而不是直接将对象引用加到列表,需要使用dict()字典添加:

cpu_frequency_msg.append(dict(cpu_frequency_data))

添加时指定值引用,类似

vcpu_5second_perf_data.append(minute_perf_data[vm][time][vcpu][cpu_index])

修正后脚本

def get_cpu_frequency_msg():
    cpu_frequency_data_output = []
    cpu_frequency_data = {}
    cpu_frequency_msg = []
    cpu_frequency_data_output = subprocess.check_output("sudo cpupower monitor -m Mperf | grep -Ev 'Mperf|CPU' | awk -F\| '{print $3\" \"$6}'", shell=True).splitlines()
    for items in cpu_frequency_data_output:
        cpu_frequency_data["name"], cpu_frequency_data["value"] = "cpu"+items.split()[0], int(items.split()[1])
        cpu_frequency_msg.append(dict(cpu_frequency_data))

    return cpu_frequency_msg

参考

Last updated