前言
在这段半个月的实习生涯中,前几天主动优化自己写的代码,还学到了分布式事物锁,有点沾沾自喜。没想到没过几天就踩到了前人埋下的雷。
正文
事情是这样的,我接手了上个实习生的工作,对原有的程序做扩展多写几个接口,有个接口需要用到高德的poi_id来获取经纬度,我发现前人已经写好了代码,我就直接粘过来用,他是将获取的经纬度作为一个列表返还。 关键代码如下
Python
location_split = location.split(",")
if len(location_split) == 2:
latitude, longitude = map(float, location_split)
coordinates_dict[poi_id] = (latitude, longitude)
实际上开发文档
我看到他的代码后粘过来后改了一下返还了个字典,直接用他的经纬度的变量作为字典经纬度的值。QAQ 结果这个老6经度写成维度,维度写成经度。
我的这个函数在拿到经纬度后向后端发送请求,但后端接到后出现了这样的情况
省市区后端没有解析出来,因为这个接口前端偷懒了,直接将表单传给了后端,因此这个post请求的负载展开后一千多行(太抽象了QAQ),其中和位置相关的地方采用了双重转码,先将那个地方转为JSON作为值,再将整个对象再转一次JSON。
导致我看这个数据的时候一脸懵逼。 试了好多次还以为是自己的问题,然后不停地改负载,最后发现了他的位置相关信息的编码是转了两次JSON......蛮抽象的
为了转码还写了个递归函数
Python
# 处理双重编码的JSON字符串(本接口中的地址部分的value就是双重编码)递归调用深层解码
def decode_double_encoded_json(data):
if isinstance(data, dict):
for key, value in data.items():
if isinstance(value, str):
try:
decoded_value = json.loads(value)
data[key] = decoded_value
except json.JSONDecodeError:
pass
elif isinstance(value, dict) or isinstance(value, list):
decode_double_encoded_json(value)
else:
pass
然后, 就在此时,打印出相关信息进行对比时发现经纬度竟然刚好相反(下图是经纬度改正后的截图)
也就是说我之前排查错误的方向,什么JSON转码,什么字典中的str是双引号单引号都错了。 然后再测试就ok了,发现经纬度错了后就往前排查调用发现是工具函数的锅,这个bug卡了我两天了,还问了领导,到最后领导都以为是JSON转码的问题。(没敢告诉他是自己省事抄了个工具函数才踩雷的)
然后我就看他的函数的调用,结果发现他的函数的调用每次都是直接调用哪个列表,因为排序是没有错的,他从未单独用过经度或维度,所以他那个三个接口一直没有报错在正常跑着,真的我哭死。。。。。。
多线程监视器的优化
最近还有个想法,去优化我写的一个监视器 源代码关键部分如下
Python
# 登录状态监视器,检查是否是登录状态,若是登录状态则将cookies和headers保存到全局变量中
def monitor_login():
global cookies,headers,login_flag
thisflag = login_flag
while True:
time.sleep(2)
# 如果调用了登录接口,尝试获取cookies和headers
if thisflag != login_flag:
# 40s后尝试登录
time.sleep(40)
is_login = browser_data()
if not is_login:
print("当前为未登录状态,20s后重新尝试")
time.sleep(20)
is_login = browser_data()
if not is_login:
print("当前为未登录状态,请检查")
else:
print("成功获取登录信息")
time.sleep(5)
登录接口的钩子函数,用来触发监视器
Python
# 发送登录响应后,通过修改全局变量触发监视器
@after_this_request
def post_callback_task(response):
global login_flag
login_flag = not login_flag
return response
注册多线程
Python
# 注册线程函数,启动后台线程来监控登录状态的变化
monitor_thread = threading.Thread(target=monitor_login)
# 守护进程
monitor_thread.daemon = True
monitor_thread.start()
个人感觉此监控器处于长期运转状态,会造成性能浪费。然后我就想能不能每次调用的登录接口的时候短暂唤醒这个线程,然后执行完后再进入沉睡,在调用接口时再唤醒。
优化测试
修改逻辑,只在触发函数后监控器运行一小段时间。能够节省时间。实验逻辑的测试样例如下:
Python
pause_event = threading.Event()
def case1():
flag =0
while True:
flag = flag+1
print(flag)
time.sleep(1)
if flag % 5 == 0:
# 冻结线程
pause_event.clear()
pause_event.wait()
# 注册线程函数,启动后台线程来监控登录状态的变化
monitor_thread = threading.Thread(target=case1)
# 守护进程
# monitor_thread.daemon = True
monitor_thread.start()
time.sleep(7)
#模拟调用接口
while True:
x = input("请输入")
if x == "1":
# 触发解禁
pause_event.set()
但将相关逻辑嫁接到项目中后主线程被阻塞。
有没有jym有好的想法和建议?