Python字符串转列表通用方法:从JSON到eval的安全实践
1. 引言在Python编程中我们经常会遇到需要将字符串表示的列表转换为实际列表对象的情况。比如从配置文件读取的字符串[qwen-turbo,qwen-plus,deepseek]或者包含对象实例的字符串[Person(Alice), Person(Bob)]。本文将详细介绍几种通用的转换方法并分析它们的适用场景和安全注意事项。2. 基础场景JSON格式字符串转列表2.1 使用json模块对于标准的JSON格式字符串json.loads()是最安全、最推荐的方法importjson# 示例1字符串列表raw_str[qwen-turbo,qwen-plus,deepseek]lsjson.loads(raw_str)print(ls)# [qwen-turbo, qwen-plus, deepseek]print(type(ls))# class list# 示例2嵌套列表nested_str[[a, b], [c, d]]nested_listjson.loads(nested_str)print(nested_list)# [[a, b], [c, d]]2.2 处理单引号问题JSON标准要求双引号但有时数据可能使用单引号。可以使用str.replace()预处理importjson raw_str[qwen-turbo,qwen-plus,deepseek]# 将单引号替换为双引号json_strraw_str.replace(,)lsjson.loads(json_str)print(ls)# [qwen-turbo, qwen-plus, deepseek]3. 进阶场景包含Python对象的字符串3.1 使用ast.literal_eval()当字符串包含Python字面量表达式时ast.literal_eval()比eval()更安全importast# 示例1基本列表raw_str[qwen-turbo, qwen-plus, deepseek]lsast.literal_eval(raw_str)print(ls)# [qwen-turbo, qwen-plus, deepseek]# 示例2数字列表num_str[1, 2, 3, 4, 5]num_listast.literal_eval(num_str)print(num_list)# [1, 2, 3, 4, 5]# 示例3混合类型mixed_str[1, hello, True, None]mixed_listast.literal_eval(mixed_str)print(mixed_list)# [1, hello, True, None]3.2 处理自定义对象实例对于包含对象实例的字符串需要更复杂的处理importastclassPerson:def__init__(self,name):self.namenamedef__repr__(self):returnfPerson({self.name})def__eq__(self,other):returnisinstance(other,Person)andself.nameother.name# 方法1使用eval仅限可信来源raw_str[Person(Alice), Person(Bob)]# 需要先定义Person类在当前作用域lseval(raw_str,{Person:Person})print(ls)# [Person(Alice), Person(Bob)]# 方法2安全解析并重建defparse_object_list(obj_str):安全解析对象列表字符串# 使用ast解析为ASTtreeast.parse(obj_str,modeeval)# 遍历AST节点提取构造信息objects[]fornodeinast.walk(tree):ifisinstance(node,ast.Call)andisinstance(node.func,ast.Name):ifnode.func.idPerson:# 提取参数args[]forarginnode.args:ifisinstance(arg,ast.Constant):args.append(arg.value)objects.append(Person(*args))returnobjects raw_str[Person(Alice), Person(Bob)]lsparse_object_list(raw_str)print(ls)# [Person(Alice), Person(Bob)]4. 通用转换函数4.1 智能转换函数下面是一个通用的智能转换函数可以处理多种格式importjsonimportastimportredefsmart_str_to_list(raw_str,safe_modeTrue): 将字符串转换为列表的通用函数 参数: raw_str: 输入字符串 safe_mode: 是否启用安全模式禁用eval 返回: 转换后的列表 # 去除首尾空白raw_strraw_str.strip()ifnotraw_str:return[]# 尝试JSON解析最安全try:# 处理单引号情况json_strraw_str.replace(,)returnjson.loads(json_str)exceptjson.JSONDecodeError:pass# 尝试ast.literal_eval相对安全try:returnast.literal_eval(raw_str)except(SyntaxError,ValueError):pass# 如果允许且必要尝试eval仅限可信数据ifnotsafe_mode:try:returneval(raw_str)except:pass# 最后尝试正则分割# 匹配引号内的内容或非空白字符patternr[\]([^\]*)[\]|([^,\s\[\]])matchesre.findall(pattern,raw_str)result[]formatchinmatches:# match[0]是引号内的内容match[1]是非引号内容itemmatch[0]ifmatch[0]elsematch[1]ifitem:# 尝试转换为数字try:if.initem:result.append(float(item))else:result.append(int(item))exceptValueError:result.append(item)returnresult# 测试各种格式test_cases[[qwen-turbo,qwen-plus,deepseek],[qwen-turbo,qwen-plus,deepseek],[1, 2, 3, 4, 5],[true, false, null],# JSON布尔值和null[a, b, c],apple, banana, cherry,]fortestintest_cases:resultsmart_str_to_list(test)print(f输入:{test})print(f输出:{result})print(f类型:{type(result)})print(-*40)4.2 带类型推断的转换defstr_to_list_with_types(raw_str): 将字符串转换为列表并自动推断元素类型 try:# 先尝试JSONresultjson.loads(raw_str.replace(,))except:try:# 再尝试literal_evalresultast.literal_eval(raw_str)except:# 最后使用简单分割result[item.strip()foriteminraw_str.strip([]).split(,)]# 类型推断和转换typed_result[]foriteminresult:ifisinstance(item,(int,float,bool,type(None))):typed_result.append(item)elifisinstance(item,str):# 尝试转换为数字try:if.initem:typed_result.append(float(item))else:typed_result.append(int(item))exceptValueError:# 尝试转换为布尔值ifitem.lower()true:typed_result.append(True)elifitem.lower()false:typed_result.append(False)elifitem.lower()nulloritem.lower()none:typed_result.append(None)else:typed_result.append(item)else:typed_result.append(item)returntyped_result# 测试test_str[1, 2.5, true, false, null, hello]resultstr_to_list_with_types(test_str)print(f输入:{test_str})print(f输出:{result})print(f类型:{[type(x)forxinresult]})5. 安全注意事项5.1 eval的安全风险# 危险示例永远不要对不可信数据使用evalmalicious_str__import__(os).system(rm -rf /)# 危险# result eval(malicious_str) # 千万不要执行# 安全替代方案defsafe_eval(expression,allowed_namesNone):受限的eval实现ifallowed_namesisNone:allowed_names{}# 编译时检查try:codecompile(expression,string,eval)exceptSyntaxError:raiseValueError(Invalid expression)# 检查允许的节点类型fornodeinast.walk(ast.parse(expression,modeeval)):ifisinstance(node,(ast.Import,ast.ImportFrom,ast.Call)):# 禁止导入和函数调用raiseValueError(Import and function calls are not allowed)returneval(code,{__builtins__:{}},allowed_names)5.2 最佳实践优先使用json.loads()处理JSON格式数据次选ast.literal_eval()处理Python字面量避免使用eval()除非完全控制数据来源验证输入数据使用白名单验证错误处理始终使用try-exceptdefsafe_str_to_list(raw_str,allowed_classesNone):安全地将字符串转换为列表ifallowed_classesisNone:allowed_classes{}# 输入验证ifnotisinstance(raw_str,str):raiseTypeError(Input must be a string)# 长度限制iflen(raw_str)10000:raiseValueError(Input string too long)try:# 尝试JSONreturnjson.loads(raw_str)exceptjson.JSONDecodeError:try:# 尝试literal_evalreturnast.literal_eval(raw_str)except(SyntaxError,ValueError):# 自定义对象处理受限ifallowed_classes:returneval(raw_str,{__builtins__:{}},allowed_classes)else:raiseValueError(Cannot safely parse the string)6. 实际应用示例6.1 配置文件解析importconfigparserimportjsonclassConfigLoader:def__init__(self,config_file):self.configconfigparser.ConfigParser()self.config.read(config_file)defget_list(self,section,key,defaultNone):从配置文件中获取列表try:valueself.config.get(section,key)returnsmart_str_to_list(value)except(configparser.NoSectionError,configparser.NoOptionError):returndefaultifdefaultisnotNoneelse[]# 配置文件内容示例# [models]# active_models [qwen-turbo, qwen-plus, deepseek]# batch_sizes [32, 64, 128]6.2 API响应处理importrequestsimportjsondefparse_api_response(response_text):解析API返回的字符串列表try:datajson.loads(response_text)# 如果API返回的是字符串形式的列表ifisinstance(data,dict)andmodelsindata:models_strdata[models]ifisinstance(models_str,str):returnsmart_str_to_list(models_str)returnmodels_strreturndataexceptjson.JSONDecodeError:# 尝试其他格式returnsmart_str_to_list(response_text)# 模拟API响应api_response{models: [\\qwen-turbo\\, \\qwen-plus\\, \\deepseek\\]}resultparse_api_response(api_response)print(f解析结果:{result})7. 性能比较importtimeitimportjsonimportast test_str[qwen-turbo,qwen-plus,deepseek,model-a,model-b]*100# 性能测试deftest_json():returnjson.loads(test_str)deftest_ast():returnast.literal_eval(test_str)deftest_eval():returneval(test_str)# 运行测试json_timetimeit.timeit(test_json,number1000)ast_timetimeit.timeit(test_ast,number1000)eval_timetimeit.timeit(test_eval,number1000)print(fjson.loads:{json_time:.6f}seconds)print(fast.literal_eval:{ast_time:.6f}seconds)print(feval:{eval_time:.6f}seconds)8. 总结本文介绍了多种将字符串转换为列表的方法json.loads()最安全适合JSON格式数据ast.literal_eval()相对安全适合Python字面量eval()功能最强但最危险仅限可信数据自定义解析函数灵活可控适合特定需求选择方法时需要考虑数据来源是否可信字符串格式是否规范是否需要处理自定义对象性能要求对于大多数场景推荐使用json.loads()或ast.literal_eval()避免使用eval()处理不可信数据。对于包含自定义对象的字符串建议使用安全的AST解析方法或限制eval的执行环境。

相关新闻

Unity游戏开发:工业级坐骑召唤系统设计与实现全解析

Unity游戏开发:工业级坐骑召唤系统设计与实现全解析

1. 项目概述:从需求到实现的完整拆解在游戏开发中,尤其是MMORPG、ARPG或者开放世界冒险类游戏里,“坐骑”系统几乎是标配。它不仅仅是玩家从一个点快速移动到另一个点的交通工具,更是角色成长、身份象征和游戏沉浸感的重要组成部分…

2026/10/28 21:42:51 阅读更多 →
WPF等待窗口开发:进度条+倒计时+监控一体化方案

WPF等待窗口开发:进度条+倒计时+监控一体化方案

1. WPF等待窗口开发实战:进度条倒计时监控功能一体化实现在桌面应用开发中,等待窗口是提升用户体验的关键组件。最近为一个工业监控项目开发了一套复合型等待窗口,整合了进度指示、倒计时提醒和后台任务监控三大功能。这种设计特别适合需要长…

2026/11/2 6:11:52 阅读更多 →
Unity中Ray Marching与Compute Shader实战:从原理到可扩展渲染框架

Unity中Ray Marching与Compute Shader实战:从原理到可扩展渲染框架

1. 项目概述:为什么要在Unity里折腾Ray Marching?如果你玩过《纪念碑谷》或者看过一些炫酷的科幻电影特效,里面那些扭曲、融合、无限重复的几何空间,是不是觉得特别酷?传统的3D建模和渲染管线,做这些效果要…

2026/11/2 17:54:23 阅读更多 →

最新新闻

Electron桌面应用开发实战:从环境搭建到打包发布全流程

Electron桌面应用开发实战:从环境搭建到打包发布全流程

做前端这些年,我大部分时间都在跟浏览器标签页打交道,直到第一次把桌面应用跑起来,才发现原来自己一直被限制在地址栏和刷新按钮围起来的框框里。Electron这个词,最开始是在某段时间频繁出现在同事的讨论里,一个用HTML…

2026/11/3 1:09:25 阅读更多 →
滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

简介:亚太天能T109滑盖智能锁产品说明书是一份PDF格式的官方技术文档,主要面向智能锁安装人员、终端用户及售后维护者,帮助快速掌握产品安装、配置与常见故障处理。全包仅1个PDF文件,大小4.37MB,内容结构清晰&#xff…

2026/11/2 10:46:11 阅读更多 →
PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

上个月我在调试一台高速AGV的驱动系统,整车要求空载跑到8m/s,电机转速已经拉到额定点,驱动器的输出电压也顶到了母线电压极限附近。再往上踩速度指令,转速纹丝不动,三相电流反而开始震荡。那会儿我的第一反应就是&…

2026/11/2 10:47:40 阅读更多 →
C++核心知识点:从内存管理到STL的实战指南

C++核心知识点:从内存管理到STL的实战指南

C 这门语言我前前后后折腾了十几年,用它写过嵌入式驱动、做过游戏服务端,也搭过基础组件库。每次看到新人一头扎进"C 核心知识点"这个搜索词,我其实挺感慨的——这门语言的难点从来不是语法多,而是知识点之间的耦合太深…

2026/11/3 2:27:21 阅读更多 →
T109滑盖智能锁怎么装?安装调试与故障排查全攻略

T109滑盖智能锁怎么装?安装调试与故障排查全攻略

简介:亚太天能T109滑盖智能锁产品说明书以PDF格式发布,适合智能锁用户、安装人员与售后维修人员阅读。内容围绕T109系列指纹密码刷卡锁展开,先介绍前面板、后面板、锁体、机械钥匙、电池盒盖等部件名称与功能,再给出完整安装步骤&…

2026/11/2 10:46:31 阅读更多 →
LLM知识降熵:从信息垄断到理解权下放

LLM知识降熵:从信息垄断到理解权下放

你有没有过这种经历:翻开源码注释、论文摘要或者一份专业报告,每个字都认识,连在一起却像天书。想找人聊聊,身边要么没人懂,要么懂的懒得跟你解释。后来我试着把同一段内容丢给一个大语言模型,几秒钟之后&a…

2026/11/2 10:46:26 阅读更多 →

日新闻

周新闻

月新闻