使用Django Pipeline执行collectstatic时出现文件找不到错误
问题详情
我的Django Pipeline配置如下:
STATIC_URL = '/static/' STATIC_ROOT = SETTINGS_DIR + '/static/' STATICFILES_DIRS = ( os.path.join(BASE_DIR, "static_files"), ) STATICFILES_STORAGE = 'pipeline.storage.PipelineManifestStorage' STATICFILES_FINDERS = ( 'django.contrib.staticfiles.finders.FileSystemFinder', 'django.contrib.staticfiles.finders.AppDirectoriesFinder', 'pipeline.finders.PipelineFinder', 'compressor.finders.CompressorFinder', 'beautycall.finders.LeftoverPipelineFinder', ) PIPELINE = { 'JAVASCRIPT': { 'main': { 'source_filenames': ( 'bower/jquery/dist/jquery.min.js', 'js/script.js', ), 'output_filename': 'compiled/main_script.js', }, 'datetimepicker': { 'source_filenames': ( 'bower/datetimepicker/jquery.datetimepicker.js', ), 'output_filename': 'datetimepicker.js' }, 'typeahead': { 'source_filenames': ( 'bower/typeahead.js/dist/bloodhound.js', 'bower/typeahead.js/dist/typeahead.jquery.js', ), 'output_filename': 'typeahead.js' }, 'remodal': { 'source_filenames': ( 'bower/remodal/dist/remodal.min.js', ), 'output_filename': 'remodal.js' } }, 'STYLESHEETS': { 'main': { 'source_filenames': ( 'css/style.scss', 'css/fonts.css', ), 'output_filename': 'compiled/main_stylesheet.css', }, 'datetimepicker': { 'source_filenames': ( 'bower/datetimepicker/jquery.datetimepicker.css', ), 'output_filename': 'compiled/jquery.datetimepicker.css' }, 'remodal': { 'source_filenames': ( 'bower/remodal/dist/remodal.css', 'bower/remodal/dist/remodal-default-theme.css' ), 'output_filename': 'remodal.css' }, 'website': { 'source_filenames': ( 'css/website/style.scss', ), 'output_filename': 'compiled/website/style.css', } } }
执行时触发以下错误:
raise CompilerError(e, command=argument_list, pipeline.exceptions.CompilerError: [WinError 2] 系统找不到指定的文件
该问题仅在Windows系统出现,Linux环境下运行完全正常。使用自定义LeftoverPipelineFinder时,Pipeline似乎无法定位source_filenames中的部分文件。
错误发生在django-pipeline的这段代码执行阶段:
compiling = subprocess.Popen(argument_list, cwd=cwd,stdout=stdout,stderr=subprocess.PIPE, shell=False)
排查过程中确认cwd参数路径正常,但用path.exists()检查argument_list中的4个参数时,发现有3个路径不存在。不清楚这种情况是否属于正常现象,也不熟悉subprocess.Popen的运行机制,求可行的解决思路。
解决思路
1. 修复路径分隔符兼容问题
Windows使用\作为路径分隔符,Linux使用/,虽然Python的os.path.join会自动适配,但配置中硬写的/分隔符可能在Windows下被解析异常:
- 把PIPELINE配置中的
source_filenames路径改为用os.path.join动态拼接,确保适配系统分隔符:'source_filenames': ( os.path.join('bower', 'jquery', 'dist', 'jquery.min.js'), os.path.join('js', 'script.js'), ), - 或者在settings中添加配置,强制Pipeline使用系统原生分隔符:
PIPELINE['PATH_SEPARATOR'] = os.sep
2. 检查自定义Finder的Windows兼容性
自定义的LeftoverPipelineFinder可能未处理Windows路径逻辑,需要:
- 确保Finder内部的路径拼接全部使用
os.path模块的方法,禁止硬写/分隔符。 - 在Finder代码中添加调试逻辑,打印返回的文件路径,用
os.path.exists()验证路径是否有效。
3. 调整subprocess的shell参数
Windows下部分命令依赖系统环境变量,需要开启shell=True才能正确执行。可以尝试修改django-pipeline的对应代码,把shell=False改为shell=True(注意:仅在可控的内部环境下使用,避免安全风险)。
4. 明确指定编译器路径
如果是编译SCSS等预处理文件,Windows下可能未正确识别编译器路径:
- 确保编译器(如node-sass、sass)的可执行文件在系统PATH中。
- 或者在PIPELINE配置中直接指定编译器的绝对路径:
PIPELINE['SASS_BINARY'] = r'C:\Program Files\nodejs\node_modules\npm\bin\node-sass.cmd'
5. 验证路径大小写一致性
Windows文件系统大小写不敏感,但Python的path.exists()会严格匹配路径大小写。检查配置中的路径和实际文件的大小写是否完全一致(例如配置写datetimepicker.js,实际文件是DateTimePicker.js)。
内容的提问来源于stack exchange,提问作者Andi Fathul Mukminin

