使用PyYAML验证YAML文件异常:非YAML文件被误判为有效
问题:PyYAML误将非YAML文件判定为有效文件
我尝试用Python的PyYAML库验证YAML文件,但发现它会把非YAML文件(比如bash脚本)也判定为有效,不符合预期。
以下是我的验证脚本,当传入bash脚本路径file_path = './testbashscript.sh'时,错误地将其判定为有效YAML文件:
#!/usr/bin/env python3 import yaml def is_yaml_file(file_path): try: with open(file_path, 'r') as file: yaml.safe_load(file) return True except: return False def main(): file_path = './testbashscript.sh' if is_yaml_file(file_path): print(f"{file_path} is a valid YAML file") else: print(f"{file_path} is not a valid YAML file") if __name__ == "__main__": main()
测试用的bash脚本内容:
#!/usr/bin/env bash echo "Hello World"
实际输出:
./testbashscript.sh is a valid YAML file
预期结果应该是判定该bash脚本为无效YAML文件,问题出在哪里?
原因分析
这不是PyYAML的bug,而是YAML语法本身的特性:
- YAML允许纯文本字符串作为合法的顶级元素(属于YAML的“纯量”类型)
- bash脚本的第一行
#!/usr/bin/env bash在YAML中会被当作注释(YAML用#开头表示注释) - 第二行
echo "Hello World"会被解析为一个字符串纯量,yaml.safe_load能正常读取,不会抛出错误,所以你的脚本返回True。
另外,你的脚本使用了except:捕获所有异常,这会掩盖其他可能的错误(比如文件读取失败),但核心问题还是对YAML合法性的判断逻辑太宽松。
解决方案
要准确区分“能被YAML解析的文本”和“实际的YAML配置文件”,可以修改判断逻辑:要求解析结果是字典或列表类型——因为绝大多数实际使用的YAML文件都是以字典(键值对)或列表作为顶级结构,纯文本字符串很少作为YAML配置的预期内容。
修改后的脚本如下:
#!/usr/bin/env python3 import yaml def is_yaml_file(file_path): try: with open(file_path, 'r') as file: data = yaml.safe_load(file) # 仅当解析结果是字典或列表时,判定为有效YAML文件 return isinstance(data, (dict, list)) except yaml.YAMLError: # 捕获YAML解析错误 return False except Exception as e: # 处理文件读取等其他异常(比如文件不存在、权限问题) print(f"Error reading file: {e}") return False def main(): file_path = './testbashscript.sh' if is_yaml_file(file_path): print(f"{file_path} is a valid YAML file") else: print(f"{file_path} is not a valid YAML file") if __name__ == "__main__": main()
修改后运行脚本,会得到预期输出:
./testbashscript.sh is not a valid YAML file
内容的提问来源于stack exchange,提问作者vjwilson
相关产品推荐
相关产品推荐

