背景

由于一些安全上的要求,笔者所在公司在阿里云上的主机都要写白名单ACL。其中一个安全组中有监控的脚本需要发消息给企业微信,然后就犯了难——企业微信并没有接口告诉我们它的URL最后会解析为哪些ip,虽然确实有一个ip接口会给一个ip列表,但那个列表用在回调的情况下,和我们直接向企业微信发送HTTP请求时解析出来的ip并不一样

好在,我找到了这么个东西——企业微信域名IP列表​res.mail.qq.com

不过,这里面关于api接口所能解析出来的ip也多的让人眼花,一个个去配策略怕是配到死去了,于是就想用阿里云上的安全组策略的json模板,把这些ip填充进去生成个json文件,这样就可以直接导入策略了……

写出了Bug……

想法有了就开干。

写出来的代码是这样的——

import json

ips = '101.89.18.158,183.57.48.50,183.61.49.203,59.37.116.103,59.37.96.203,59.37.96.177,183.3.224.149,183.3.234.106,' \

'219.133.60.224,59.37.116.102,101.227.162.152,101.226.49.50,163.177.56.117,140.207.189.106,220.249.243.155,' \

'157.255.173.237,58.251.80.106,58.251.61.195,223.167.84.62,116.128.138.160,220.249.243.71,163.177.72.150,' \

'163.177.83.223,163.177.90.33,183.232.95.169,117.184.242.103,183.192.202.172,183.232.94.38,183.232.126.25,' \

'183.232.119.142,183.232.95.88,183.232.88.200,183.232.126.115,121.51.86.66,182.254.34.111,121.51.130.85,' \

'182.254.34.156,182.254.34.69,182.254.78.66,203.205.255.254,182.254.34.63,182.254.38.24,203.205.219.41,' \

'121.51.140.149,182.254.38.32,182.254.5.199,182.254.11.176'

ipslist = ips.split(",")

PolicyList = []

DictTemplate = {

"Policy": "Accept",

"Description": "访问微信接口",

"Priority": 1,

"NicType": "intranet",

"Direction": "egress",

"PortRange": "443/443",

"IpProtocol": "TCP",

"DestCidrIp": ""

}

for i in range(len(ipslist)):

DictTemplate["DestCidrIp"] = ipslist[i] + "/32"

PolicyList.append(DictTemplate)

print(json.dumps(PolicyList, ensure_ascii=False, indent=2))

当然,毫无疑问的,这个代码的运行是有问题的……

[

{

"Policy": "Accept",

"Description": "访问微信接口",

"Priority": 1,

"NicType": "intranet",

"Direction": "egress",

"PortRange": "443/443",

"IpProtocol": "TCP",

"DestCidrIp": "182.254.11.176/32"

},

{

"Policy": "Accept",

"Description": "访问微信接口",

"Priority": 1,

"NicType": "intranet",

"Direction": "egress",

"PortRange": "443/443",

"IpProtocol": "TCP",

"DestCidrIp": "182.254.11.176/32"

},

{

"Policy": "Accept",

"Description": "访问微信接口",

"Priority": 1,

"NicType": "intranet",

"Direction": "egress",

"PortRange": "443/443",

"IpProtocol": "TCP",

"DestCidrIp": "182.254.11.176/32"

},

......

]

"DestCidrIp" 的值是一样的……Why?

因为这里——

for i in range(len(ipslist)):

DictTemplate["DestCidrIp"] = ipslist[i] + "/32"

PolicyList.append(DictTemplate)

起初我以为,只要这样子,就可以把IP循环变成字典,然后插入到新的列表中,当然,实际上不行,因为我并非把某个值插入到了新的列表里,而是把整个字典对象放入了列表里,换言之,我的列表里实际的内容等于是——

[DictTemplate, DictTemplate, DictTemplate, DictTemplate, ......]

所以,每次循环,DictTemplate发生变化,列表里所有的元素都会变化……结果就是我输出的列表中的所有元素都一样,因为它们本来就是对应了同一个对象

当我操作一个列表的时候,我会用索引来访问值,而当我需要构建一个完整的字典的时候,我不可能只需要字典的值,字典里的键同样是我需要的东西,但是如果像上面这样做,结果就是我只是在重复的导入同一个对象,故而列表中充斥着同样的元素

修Bug……

知道了错在哪,问题就好解决了,Python的字典类型有个方法,copy()

for i in range(len(ipslist)):

DictTemplateCopy = DictTemplate.copy()

DictTemplateCopy["DestCidrIp"] = ipslist[i] + "/32"

PolicyList.append(DictTemplateCopy)

在操作字典对象之前,创建一个浅复制的对象,然后对这个对象进行操作并插入到列表中,再次循环的时候会再次创建另一个浅复制的对象,当然,之前那个对象就消失了

在交互式解释器里可以做这样一个实验

>>> DictTemplate = {

... "Policy": "Accept",

... "Description": "访问微信接口",

... "Priority": 1,

... "NicType": "intranet",

... "Direction": "egress",

... "PortRange": "443/443",

... "IpProtocol": "TCP",

... "DestCidrIp": ""

... }

>>>

>>> copy = DictTemplate.copy()

>>> print(id(copy))

2109669840920

>>> copy = DictTemplate.copy()

>>> print(id(copy))

2109670360392

>>> copy = DictTemplate.copy()

>>> print(id(copy))

2109669840920

>>> copy = DictTemplate.copy()

>>> print(id(copy))

2109670360392

不难看出,每次执行 copy = DictTemplate.copy() 后,打印其内存地址,该地址至少和上一次是不一样的。放在for循环里,就等于每次都是一个新的对象。

如此一来,执行结果就正常了——

[

{

"Policy": "Accept",

"Description": "访问微信接口",

"Priority": 1,

"NicType": "intranet",

"Direction": "egress",

"PortRange": "443/443",

"IpProtocol": "TCP",

"DestCidrIp": "101.89.18.158/32"

},

{

"Policy": "Accept",

"Description": "访问微信接口",

"Priority": 1,

"NicType": "intranet",

"Direction": "egress",

"PortRange": "443/443",

"IpProtocol": "TCP",

"DestCidrIp": "183.57.48.50/32"

},

{

"Policy": "Accept",

"Description": "访问微信接口",

"Priority": 1,

"NicType": "intranet",

"Direction": "egress",

"PortRange": "443/443",

"IpProtocol": "TCP",

"DestCidrIp": "183.61.49.203/32"

},

{

"Policy": "Accept",

"Description": "访问微信接口",

"Priority": 1,

"NicType": "intranet",

"Direction": "egress",

"PortRange": "443/443",

"IpProtocol": "TCP",

"DestCidrIp": "59.37.116.103/32"

},

{

"Policy": "Accept",

"Description": "访问微信接口",

"Priority": 1,

"NicType": "intranet",

"Direction": "egress",

"PortRange": "443/443",

"IpProtocol": "TCP",

"DestCidrIp": "59.37.96.203/32"

},

......

]

P.S. 日常写代码习惯于把功能都封装在模块里,模块之间变量隔离,因此就不会碰到这个情况。如果每次append的对象都是函数调用返回的结果,那么每次append进去的,一定是不同的对象。

python实训的意义_[Python] 一个让我更加清楚地理解了字典的实验……相关推荐

  1. 大学python实训总结-千锋Python实训总结 学好基础才能走的更远

    时间飞逝,不知不觉在千锋学习Python已经一个月了,在这不长不短的一个月时间感觉我以往的生活方式和学习方式完全被改变了,希望我能继续保持这样的求学心态和学习态度.下面这个Python实训总结就是我对 ...

  2. python实训目的意义_Python实训第二天--基础知识2

    '''''' ''' 列表: 定义: 在[]内,可以存放多个任意类型的值, 并以逗号隔开. 一般用于存放学生的爱好,课堂的周期等等... ''' # 定义一个学生列表,可存放多个学生 # list([ ...

  3. python实训目的意义_20193120 实验四 Python综合实践

    设计初衷: 程序设计来是面向实际使用过程的,不是为了程序而设计程序. 期末考试临近,最初记录平时作业成绩的时候,没有把每次分数统计的Excel表格整合在一起,最后老师需要课代表把所有的平时作业成绩汇总 ...

  4. python实训报告心得体会-Python学习心得体会

    首先最开始,我们要明确一点,学习编程不是一日之功,需要每天投入时间学习,也不可纸上谈兵,需要自己亲自操作,不动手就不会发现问题,动了手印象才会深刻,记得更靠. 接下来我就稍微总结一下,我在学习中遇到的 ...

  5. python实训日志_Logbook:Python 快速日志记录实践

    原标题:Logbook:Python 快速日志记录实践 作者:东东 yasking

  6. 初学Python实训心得以及一个爬虫例子

    了解Python,学会Python,实战python 通过这次Python实训,我收获了很多,一方面学习到了许多以前没学过的专业知识与知识的应用,另一方面还提高了自我动手做项目的潜力.本次实训是对我潜 ...

  7. Python实训day11pm【大作业简略解析】

    Python实训-15天-博客汇总表 目录 1.课堂笔记 2.群消息 3.代码 3.1.demo1 3.2.demo2 1.课堂笔记 大作业题目思路引导: 题目1:定时爬取每个地级市的实时天气状况.存 ...

  8. Python实训day07am【爬取数据接口、webdriver、自动化测试工具selenium】

    Python实训-15天-博客汇总表 目录 1.网络爬虫-课后练习题 1.1.写法1 1.2.写法2 2.Selenium自动化测试工具 2.1.安装工具 2.2.命令行操作 直接爬取HTML (30 ...

  9. Python实训day03pm【列表生成式、非文本文件的读写与复制、文本文件读写练习】

    Python实训-15天-博客汇总表 目录 1.列表生成式 2.列表的嵌套 2.1.习题1 2.2.习题2 3.非文本文件的读写 3.1.读取文件的大小 3.2.复制文件 4.课堂练习 列表生成式 非 ...

最新文章

  1. 《C陷阱与缺陷》一导读
  2. 解决Lync Server 2013无法共享演示PPT
  3. 人工智能、应用、程序
  4. OS / Linux / 主线程退出了,子线程会退出吗?
  5. android版本sdk api对应,Android API Level与sdk版本对照表
  6. mysql约束_Mysql约束条件
  7. 水滴石穿C语言之static辨析
  8. 【MySQL】MySQL常见的读写分离方法
  9. Enterprise Library Policy Injection Application Block 之二: PIAB设计和实现原理
  10. react根据中文获取拼音_react下将输入的汉字转化为拼音
  11. 小程序图片src本地服务器路径,微信小程序 图片加载(本地,网路)实例详解...
  12. 与时俱进的迅捷多功能转换器
  13. webbrowser1 脚本报错_webbrowser脚本错误的解决办法
  14. ERROR - org.apache.flume.SinkRunner$PollingRunner.run(SinkRunner.java:158)] Unable to deliver event.
  15. google翻译出错什么原因?翻译英文页面时中文闪了下就显示“翻译出错请重试”
  16. jQuery悬浮QQ客服插件
  17. ArcGIS制作栅格动图
  18. 【对抗攻击论文笔记】Enhancing the Transferability of Adversarial Attacks through Variance Tuning
  19. mysql 一个月以前_mysql查询昨天 一周前 一月前 一年前的数据
  20. 哈工大的计算机科学与技术三个校区区别,哈尔滨工业大学计算学部研招拟录三地比较,深圳校区初试分数最高...

热门文章

  1. js 有关object 、array 等引用类型的赋值问题
  2. golang入门小记
  3. dockerfile写法和docker-compose和docker-compose.yml
  4. 闭包的示例_用示例解释JavaScript中的闭包
  5. 在SQL中检查约束-用MySQL和SQL Server语法示例解释
  6. instagram架构_通过创建Instagram副本学习Laravel
  7. python web应用_如何使用Python将通知发送到Web应用
  8. mac安装go语言环境
  9. 【读书笔记】非暴力沟通
  10. 阿里云+wordpress搭建个人网站及博客