Django 1.11.7+Django Compressor在Windows10下的LP_OVERLAPPED类型错误
解决Django 1.11.7 + Windows 10下Django Compressor解锁文件的TypeError问题
嘿,我之前维护老Django项目时碰到过一模一样的问题!这个错误根源是Django 1.x版本在Windows环境下处理文件锁的一个兼容性bug——具体是django.core.files.locks里的UnlockFileEx函数传递OVERLAPPED结构体时出现了类型不匹配。虽然首页和CSS文件的锁操作能正常运行,但JS/LESS压缩后的文件保存解锁时刚好触发了这个bug,这是不同场景下文件流处理逻辑的差异导致的。
快速临时修复
直接修改Django源码里的锁处理逻辑就能解决,步骤如下:
- 找到你Python虚拟环境(或全局Python)中的Django安装目录,定位到
django/core/files/locks.py文件。 - 找到
UnlockFileEx的调用代码(大概在第86行左右),原代码是:
UnlockFileEx(handle, 0, -1, -1, overlapped)
- 把最后一个参数改成
byref(overlapped),显式传递指针引用,修改后代码为:
UnlockFileEx(handle, 0, -1, -1, byref(overlapped))
- 重启Django服务,再访问内部页面就不会报错了。
长期解决方案
如果不想修改源码,还有两个更稳妥的方向:
- 升级Django版本:这个文件锁的bug在Django 2.x及以上版本已经被官方修复,如果你的项目能兼容升级,直接切换到LTS版本(比如Django 3.2),从根源解决问题。
- 替换压缩工具/锁实现:暂时无法升级的话,可以把yuglify换成
rjsmin和rcssmin作为JS/CSS过滤器,它们的文件处理逻辑不会触发这个Windows锁的问题;或者给Django Compressor配置自定义的文件锁机制,绕开原生的Win32锁实现。
为啥首页和CSS操作没问题?
其实是因为首页的文件锁操作处于不同的文件流上下文,或者文件大小、处理时机的差异,导致OVERLAPPED结构体的传递刚好没触发类型检查的报错;而JS/LESS压缩后的文件保存时的解锁操作,刚好命中了这个类型不匹配的边界情况。
内容的提问来源于stack exchange,提问作者Keith
相关产品推荐
相关产品推荐

