Cherrypy技术问询:globals()为何有时缺失模块函数及a_builder页面偶发404?
首先得明确:globals()返回的是当前执行作用域的全局命名空间字典。当你的模块被另一个模块导入时,Python会执行模块的顶层代码(也就是不在任何函数/类内部的代码),所有顶层定义的函数、变量都会被加入模块的globals字典里。如果出现缺失,大概率是这几个场景:
条件性函数定义:如果你的函数是在
if/else这类条件块里定义的,当导入模块时条件不满足,函数就不会被创建,自然不会出现在globals()里。比如:# 你的模块代码 import os if os.environ.get("DEBUG") == "True": def debug_only_func(): pass如果导入时DEBUG环境变量没设为True,
debug_only_func就不会出现在globals()里。模块导入缓存未更新:Python会缓存已导入的模块(存在
sys.modules里)。如果你修改了模块代码后,没有重新启动解释器或者强制重新加载模块,导入的还是旧版本的模块,新添加的函数自然不在globals()里。这种情况在开发时很常见,尤其是修改代码后直接重新运行调用脚本,而没重启进程。错误的作用域调用:如果你是在某个函数内部调用
globals(),注意这里的globals()返回的是该函数定义所在模块的全局命名空间,而不是调用该函数的模块的。如果你的函数是在其他模块定义的,那调用它时的globals()就不是你当前模块的。
你提到修改a_builder代码后常触发这个问题,结合前面的模块缓存问题,我觉得大概率和缓存或代码变更后的请求不一致有关:
模块缓存导致旧代码仍在运行:修改a_builder代码后,Python可能还在使用缓存的旧模块版本,导致生成的请求URL/参数还是旧的,而旧资源已经被移除,所以返回404。解决方法是在开发时强制重新加载模块,比如用
importlib.reload():import importlib import a_builder importlib.reload(a_builder)不过生产环境不建议这么做,开发时用用没问题。
代码修改导致请求URL错误:修改网页内容时,可能不小心改了请求的URL路径、查询参数或者域名,比如拼写错误、路径少了个斜杠,导致请求的资源不存在。这种情况可以在a_builder里加日志,把每次请求的URL打出来,对比修改前后的URL是否正确。
服务器端缓存或资源更新延迟:如果你请求的是第三方网页,可能对方服务器有缓存,修改代码后你请求的新内容还没被服务器同步,或者对方已经移除了旧资源但你还在请求旧路径。这种情况可以尝试在请求里加随机参数(比如
?t=时间戳)来绕过缓存。a_builder内部的缓存机制:如果a_builder自己实现了请求缓存(比如把之前的请求结果存在内存或文件里),修改代码后缓存没清空,导致返回的是旧的404结果。检查下a_builder里有没有缓存相关的逻辑,比如用
lru_cache装饰器或者自定义的缓存字典,修改代码后需要清空这些缓存。
内容的提问来源于stack exchange,提问作者At0micr3d




