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是正确输出了预想中的命令的每行输出,但是append到cpu_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_data被append到列表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