发布于: 2023-7-6最后更新: 2023-7-25字数 00 分钟

有一个类似的示例:
有两个文件app.py、test1.py.
app.py
test1.py
执行python app.py,”/test1”的url能注册进去吗,答案是不能。
为什么呢。
我们加上调试信息:
app.py
test1.py
同时修改app.route的源码:
调试信息如下:(add url)
 
分析调用过程:
  1. 首先进入app.py,初始化app,可以看到第一条语句”create app”,然后是注册app中url,然后导入test1,这个时候在app中是不包含app的module的,这是当然的,app.py里也没有import app。
  1. 进入test1,这个时候碰到第一句from app import app ,按照 总结的module导入规则,就是在sys.modules里面去找这个模块,如果找不到,就实例化这个module模块的对象,然后从新的这个对象中,取出import进来的对象。这里可以看到,test1中判断是没有app的module的。因此,在start init test1 以后,继续进入了app.py文件,又输出了一个create app !相当于是把app.py又执行了一次。可以看到后面的add url又出现了一次,import test1 也是。但这里不会循环引用,因为app中也没有引用test1的内容,只是import,发现已经import 过了(import会先添加到sys.module里面,然后再执行,可以看到导入app里面,已经出现了app get app)就会跳过。这个时候算是完成了from app import app 这句话。
  1. 前面重点是,test1中取得的app,是test1中重新初始化一次的app!和app.py里的app不是一个。那之后的add url,也是加到这个新的app中。而在main里面,我们启动的是app.py里的py,因此,显然我们无法从浏览器访问到test1这个url。(但是如果在test1中,app.run,这个是能访问到所有url的)
怎么办呢?
从app.py中拆分一个run.py出来。
这是因为为什么不对,就是test1中重新实例化一个app,而为什么重新实例化一个app,是因为app不存在sys.module里面,因此只需要在调用test1时,app已经被人导入过就好办了。因此,应该将main拆分到一个单独的文件中。
可以看看新的调试信息
这个时候只有一个create app 了,同时这次app里直接就输出了app get app .
 
启示:
这个示例有好几个重要的作用:
  • 一是深入理解python的执行过程,以及module导入的本质概念。
  • 不要导入作为main的包,会重复执行。作为替代,分解到单独的、简单的一个py中。
  • 所有module都导入到sys.module中,重复被后续所使用。即一个包只有被运行一次。
  • 根据上一点,这就能够借助monkey patch,先导入包的地方,对包进行动态变更,则后续再导入这个包的地方都会使用到变更后的函数。这就是动态语言的魔性。
扩展:
  • 虽然用的是同一份包的内容,但要注意的是,导入到当前module时,会包含在当前module的命名空间中
  • 因此如果使用monkey patch在这里直接修改导入后的对象是没用的,该对象仅作用于当前空间,需要使用导入包.对象去访问唯一的对象。
这里对于jwt_required这个对象,只有当前文件使用,修改这个对外界是没有影响的,除非其他地方import该文件的jwt_required,相反,后面对于flask_jwt_extended.jwt_required,是全局通用的。后续的所有地方去import flask_jwt_extended.jwt_required都会使用变化后的函数。

2023年7月25日分享
2023年7月25日分享
重装系统
重装系统

该文档介绍了作者升级系统盘的过程,包括准备系统、装机、个性化、软件和工作等方面。作者提供了一些有用的技巧和软件,例如KMS激活工具、C++ redist包、Mactype、noMeiryoUI等。此外,作者还分享了一些自己的个性化设置,例如黑色任务栏、自定义光标、UWP软件设置等。