新手python入门之debug=True自动编译原理
来源:互联网 发布:mac和win7传输文件工具 编辑:程序博客网 时间:2024/06/05 20:20
本人菜鸟一只,大大们若看过后请多多指正(因为自己也是新手,难免有很多错误,请大家指正下哈),当然如果还有像我这样的小菜,咱可以一起交流交流
大家在编写python程序的时候有没有重复这样一个步骤: ya ,***(执行py文件后渲染模板出现500,或py执行程序里直接报错),然后找呀找,发现错误啦,怒改之,关闭py再运行,又出现错误,looping~~~,所以这样的过程无疑是繁琐的,tornado提供了autoreload这个模块,从此再也不用重启再运行了。
这里我们利用tornado的那个hello.py和图形化界面的IDE--pyCharm。
Hello.py代码:
import tornado.ioloopimport tornado.web class MainHandler(tornado.web.RequestHandler): def get(self): self.write("Hello, world")application = tornado.web.Application([ (r"/", MainHandler),], debug = True)if __name__ == "__main__": application.listen(8888)tornado.ioloop.IOLoop.instance().start()
当然作为菜鸟的我有很多疑问,__name__ == “__main__”是什么?百度翻贴发现,其实这个是为了判断操作者是import这个py还是直接运行这个py,如果是在交互环境import这个py,那么我们永远不会走入if语句的内容,因为__name__的名字已经变成当前的模块名hello了。在这里,我们是先对application先实例化再判断,当然如果我们把一步步在交互换将输入这些代码 #在if __name__ == "__main__":前的代码,再加上:
application.listen(8888)
#选择监听端口
tornado.ioloop.IOLoop.instance().start()
#笔者猜这里是类似C++的单列模式singleton,开始初始化instance()
if not hasattr(cls, "_instance"): cls._instance = cls()return cls._instance
这样我们依旧能再localhost:8888下访问到我们的网页。
好吧,现在来谈谈application实例化吧,在这里下个断点,debug运行,断了下来,F7进入application构造函数:
def __init__(self, handlers=None, default_host="", transforms=None, wsgi=False, **settings): if transforms is None: ''' 省略部分代码''' else: ''' 省略部分代码''' if self.settings.get("static_path"):#找到一些熟悉的了, static_path,handler参数的传入赋值 path = self.settings["static_path"] handlers = list(handlers or []) static_url_prefix = settings.get("static_url_prefix", "/static/") handlers = [ (re.escape(static_url_prefix) + r"(.*)", StaticFileHandler, dict(path=path)), (r"/(favicon\.ico)", StaticFileHandler, dict(path=path)), (r"/(robots\.txt)", StaticFileHandler, dict(path=path)), ] + handlers if handlers: self.add_handlers(".*$", handlers)#关键部分,import了autoreload模块,顾名思义,在start处跟进去 # Automatically reload modified modules if self.settings.get("debug") and not wsgi: import autoreload autoreload.start()
autoreload.py:
def start(io_loop=None, check_time=500): io_loop = io_loop or ioloop.IOLoop.instance() #start后io_loop也就赋值了 modify_times = {}callback = functools.partial(_reload_on_update, io_loop, modify_times)#partial函数,绑定一部分参数,简化参数的输入#scheduler = ioloop.PeriodicCallback(callback, check_time, io_loop=io_loop)#PeriodicCallback,我猜是定时调用函数callback,参数中check_time=500意味500s调用一次,io_loop = io_loop说明前俩参数是必写的,这个呢函数会帮你赋值scheduler.start() #跟进去
Ioloop.py里classPeriodicCallback::
def start(self): self._running = True timeout = time.time() + self.callback_time / 1000.0 #callback_time即传入的check_time=500,/1000变成500ms了 self.io_loop.add_timeout(timeout, self._run) #进入后发现timeout传进了deadline,我猜是半秒执行一次这个实例对象scheduler(猜错别骂~),
现在我们返回来看看autoreload.py里的_reload_on_update:
def _reload_on_update(io_loop, modify_times): global _reload_attempted if _reload_attempted: # We already tried to reload and it didn't work, so don't try again. return for module in sys.modules.values(): # 检测内存中已有的模块(import过的) if not isinstance(module, types.ModuleType): continue #这里搜索ModuleType类的对象 path = getattr(module, "__file__", None) #path赋值为当前的模块文件名 if not path: continue if path.endswith(".pyc") or path.endswith(".pyo"): path = path[:-1] #统一变成*.py格式的文件名 try: modified = os.stat(path).st_mtime· #st_mtime: time of most recent content modification.把path即当前模块最后修改时间入modified. except: continue if path not in modify_times: modify_times[path] = modified Continue #把这些模块st.mtime信息存入modify_times以便对比发现是否模块做出新的修改 if modify_times[path] != modified: logging.info("%s modified; restarting server", path) _reload_attempted = True #检测到模块文件做出了新的修改后重启服务器: for fd in io_loop._handlers.keys(): try: os.close(fd) except: Pass #重启前先关闭所有IO事件,关进程了 if hasattr(signal, "setitimer"): #检查信号中是否设置了计时器 # Clear the alarm signal set by # ioloop.set_blocking_log_threshold so it doesn't fire # after the exec. signal.setitimer(signal.ITIMER_REAL, 0, 0) #原型signal.setitimer(which, seconds[, interval]),在经过seconds时间后触发which(signal.ITIMER_REAL, signal.ITIMER_VIRTUAL or signal.ITIMER_PROF),并且 #以后每隔interval时间进行fire。经过interval时间后,一个信号会被发送给进程.interval设置为0,表示清除该alarm signal。 try: os.execv(sys.executable, [sys.executable] + sys.argv)#os.execv:启动新进程,os.spawnv:后台执行程序#用sys.executable即解释器(我这里是pythn.exe,可以自己在交互环境import sys#后查看) sys.argv命令行第一个参数不就是cmd下我们输入python *.py的”*.py”吗#意思就是用python.exe打开这个.py吧 except OSError: os.spawnv(os.P_NOWAIT, sys.executable, [sys.executable] + sys.argv) sys.exit(0)#Mac OS X versions prior to 10.6 do not support execv in a process that contains #multiple threads. So using spawnv instead.
对于autoreload.py,大家可以参考下这个https://github.com/tornadoweb/tornado/blob/master/tornado/autoreload.py代码解释很清晰。到这里,我已经把debug=True时代码自动编译的原理水了一边了.
过程:
<1>在application实例化时检测有没debug字眼:if self.settings.get("debug") and not wsgi:
<2>有则autoreload.start()
<3>设置回调函数callback = functools.partial(_reload_on_update, io_loop, modify_times) 与 scheduler = ioloop.PeriodicCallback(callback, check_time, io_loop=io_loop)
<4>然后就可以在指定check_time下刷新_reloader_on_update函数。
- 新手python入门之debug=True自动编译原理
- Tornado"debug=True"动态编译
- 新手之eclipse debug入门简易教程
- eclipse debug调试(送给入门级”童靴“)之新手上路
- python flask框架 app.debug=True时,启动脚本被执行了2次
- Debug "somebool == true" 的陷阱
- 新手Python入门+环境搭建
- studio android.useDeprecatedNdk=true解决ndk提示版本低不能自动编译jni
- 编译原理入门
- 微机原理之汇编语言程序部分的入门实验——DEBUG的使用
- <compilation debug="true" targetFramework="4.0"> 解决方案
- <compilation debug="true" targetFramework="4.0">的解决
- <compilation debug="true" targetFramework="4.0">的解决
- Python 新手之 Joseph 问题
- 新手学Android之如何以正确的姿势debug
- python新手笔记之python继承
- <Context path="" docBase="reports" debug="0" reloadable="true"/> 中 debug 参数解释
- ARM 编译连接原理入门
- Vector和ArrayList的区别
- OSCache缓存框架学习
- mysql的优化步骤
- 题目1062:分段函数 题目1063:整数和 题目1064:反序数 题目1065:输出梯形
- 第十二周项目1.4 十进制与二进制扯不开的关系
- 新手python入门之debug=True自动编译原理
- javabase简记--第四天
- Linux makefile中的= := ?=操作符
- Android Parcelable和Serializable的区别
- 让IS NULL走起索引
- 第十二周项目2 烧脑的汉诺塔
- c++学习笔记二
- 第十二周项目四:银行系统(一)
- 浅谈django 和 get post 方法