一. 不同环境下的调试
使用flask+python写一个博客,并在新浪云sae的环境当中部署.
博客网址https://fengyunlsm.applinzi.com/
博客代码托管于github
参考资料:http://abirdcfly.github.io/2016/03/07/flask-to-sae/#
应用场景 :不同环境或平台下测试
1.什么是不同环境下的调试:
开发环境:ubuntu16.04.1, python2.7.11
生产环境:python2.7.5, 新浪云sae
2.出现什么问题?
在新浪云sae的环境中,当我使用管理员账号登陆的时候,查看不了需要权限的归档标签和点滴标签.而实际上是可以查看到这两个标签
在本地开发环境当中,可以查看到这两个标签(归档和点滴)
3.那么我一开始是怎么调试,然后经过了一个什么过程,有了灵感进行了新的调试
比较正常运行的情况下和不能正常运行的情况下的差异,找出他们的不同点(不同点是什么),逐个排除(如何逐个排除)
3.那么不同点在哪?
配置(config.py)
原代码如下:
class ProductionConfig(Config): SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or 'sqlite:///' + os.path.join(basedir, 'data.sqlite')
修改后的代码如下:
1 class ProductionConfig(Config): 2 3 SQLALCHEMY_DATABASE_URI = 'mysql://%s:%s@%s:%s/%s' 4 % (sae.const.MYSQL_USER, sae.const.MYSQL_PASS, 5 sae.const.MYSQL_HOST, int(sae.const.MYSQL_PORT), sae.const.MYSQL_DB)
启动文件(manage.py)
原代码如下:
1 #!/usr/bin/env python 2 # -*- coding: utf-8 -*- 3 4 app=create_app(os.getenv('FLASK_CONFIG') or 'default')#develop to use
修改后的代码如下:
1 #!/usr/bin/env python 2 # -*- coding: utf-8 -*- 3 4 if os.environ.get('APP_NAME') is None: 5 check = 'development' 6 else: 7 check = 'production' 8 9 10 app = create_app(os.getenv('WOTER_CONFIG') or str(check))
如何逐个排除(采用控制变量法进行排除)
先排除config.py文件当中的差异,在配置文件config.py中将FLASK_CONFIG的值改'production'
但是遇到的问题是新浪云sae和本地开发环境也是有区别的,区别在于环境不一样,本地环境是python2.7.11,而sae的本地环境是python2.7.5(这个差异我之前是认识不到的,后来才意识到,这是后话),我之前只是大概知道环境不一样,具体差异在哪,我是不清楚的.
那么接下来我们需要解决的问题就是:模拟生产环境或直接在生产环境当中调试
我就按照google出来的网址 里面的模拟生产环境 新浪提供的调试工具,然后我又遇到了一个问题就是基本使用里面的dev_server.py是怎么用的?也是坑在这里,由于新浪文档没有很详细的说明这个文件(dev_server.py)的使用方法,并且我尝试了google也搜索不了相关的使用方法,导致在这个坑停滞不前.并且在猜想是不是版本的问题,指的是上传的site-packages里面的模块版本号与新浪云原来的版本号不一样,导致冲突,那么就产生还是两个后果:(1)新浪云使用的是site-package里面的模块;(2)另一个就是新浪云使用的是自己版本,但是由于无法观察到版本号是否正确(指的是site-package里面的版本号),因此也停滞不前
那么我在什么时候发现了解决问题的办法呢?
是在一次吃饭的过程当中,而之前却是找到不到任何思路,而这一机灵的产生估计是跟这个酝酿效应有关系.
那么是什么解决方法呢?
改变搜索的关键字,原来是搜索python+sae或新浪云,现在直接改成搜索新浪云,然而在这篇文章当中找到例子,解决了dev_server.py是怎么用的问题.但是这个始终是模拟新浪云环境测试环境,而并不是实际当中的新浪云,因此即使在测试环境中没有问题(经测试,确实没有问题),但是在新浪云的环境当中依然存在问题(即使用户有权限但是依然不能点击打开网页关于和归档),所以问题再一次出现,又出现停滞不前的现象
那么我又是什么时候把问题(即使用户有权限但是依然不能点击打开网页关于和归档)解决了?
是在一次睡完午觉的时候,萌萌隆隆
3.结论:必须建立反馈(知道输入输出)
二.保持审计跟踪
什么是保持审计跟踪
实际上就是我们的单步调试,有时候无法进行单步调试,需要使用print函数。
什么时候用到审计跟踪
当我们不知道程序运行的过程的时候,或者我们对程序流程比较模糊的时候。
print函数用于确定程序运行到哪里。
怎么做
首先,当程序过于复杂的时候,我们先写下来(事情超过两层逻辑);当简单的时候(一层逻辑),没必要写。
其次,先把自己认为的流程写下来,和程序运行出来的流程作比较,然后比较两者之间的差异,来发现我们认为的过程是否出现错误。
再者,如果程序过程也没有错误,那么我们就要考虑是不是理解概念的时候出现了偏差。
‘’‘这一片需要修改
假设时间发生的流程A ->B -> C ->D
那么我们应该在B和C之间插入一个print函数,这样就可以快速排除是A ->B 的错 还是 C->D的错
假设事情发生的流程A -> B -> C ->D B -> E
也就是出现了分支
如果我们想确认问题是在C那里还是E那里
那么在B和C之间插入print函数,以及在B和C之间插入print函数
’‘’
事例1
问题:多线程出现问题,要么流程,要么概念出现问题,而刚好多线程的概念就是流程本身。
解决方案:使用
事例2
问题:我在画快排的流程图的时候,发现无法总结出左排序中的 i 值和 j 值的规律,那么我们就猜想有可能是我的自己认为的快排流程出错。
解决方案:对于快排,将分为以下几个方面去考虑(上一行是否对下一行影响,是否是这一行(还没完)
三.分而治之
什么是分而治之,类似二分查找法
在程序不同的地方设置print,看是否输出应该要输出的数值
什么时候使用分而治之:
当我只知道程序运行到一个较大的范围(1-9行)的时候,我们不知道程序运行到哪一个较小的范围而导致出现错误,是(6-7行)还是(8-9行),这时候,可以分别在第六行和第7行之间,第8行和第9行之间插入print函数。
print函数用于确定那个范围出现错误和预期不一致的错误。
怎么做
假设时间发生的流程A ->B -> C ->D
那么我们应该在B和C之间插入一个print函数,这样就可以快速排除是A ->B 的错 还是 C->D的错
假设事情发生的流程A -> B -> C ->D B -> E
也就是出现了分支
如果我们想确认问题是在C那里还是E那里
那么在B和C之间插入print函数,以及在B和C之间插入print函数
如下列程序:
1 def tcp_ser_get_get(): 2 while True: 3 if not rec_queue.empty(): 4 val = rec_queue.get(1) 5 print (u'发送的数据为{0}'.format(val)) 6 if re.match('customer1', val): 7 tcpclisock[1].send(val) 8 else: 9 tcpclisock[0].send(val)
四.一次只修改一个地方
参考资料:《调试九法》