在实际开发中我们经常会遇到这样的数据看起来像list实际上是str看起来像对象实际上只是对象的字符串描述从日志、数据库、接口返回的数据中恢复 Python 对象今天通过两个真实案例讲解如何正确处理。一、问题一字符串形式的 List 如何转换成真正 List1.1 场景例如raw_str [qwen-turbo,qwen-plus,deepseek]很多初学者会认为print(type(raw_str))应该是class list但是实际print(type(raw_str))结果class str原因它只是一个字符串。里面的[qwen-turbo,qwen-plus,deepseek]只是字符。1.2 错误方式eval()很多人第一反应result eval(raw_str)结果[qwen-turbo, qwen-plus, deepseek]看起来可以。但是不推荐原因eval()会执行 Python 代码。例如data __import__(os).system(rm -rf /) eval(data)如果数据来自用户输入网络请求数据库可能造成安全问题。1.3 推荐方式ast.literal_eval()Python 提供安全解析import ast raw_str [qwen-turbo,qwen-plus,deepseek] models ast.literal_eval(raw_str) print(models) print(type(models))输出[qwen-turbo, qwen-plus, deepseek] class list1.4 literal_eval 支持哪些类型例如list[a,b]转换[a,b]dict{name:deepseek}转换{ name:deepseek }tuple(1,2,3)转换(1,2,3)二、问题二字符串中的 Document 对象如何获取 page这是 RAG 项目中非常常见的问题。例如[Document(metadata{pk:12,page:2}, page_contentxxx)]很多人看到Document以为documents[0].page_content可以访问。但是实际上type(data)结果class str它不是 Document。只是一个包含 Document 文本描述的字符串。三、为什么不能直接取 page错误data [Document(metadata{page:2},page_contenthello)] print(data[0].page)错误AttributeError因为data实际结构String | | 字符 | | [ D o c u m e n t ( ... )Python 不知道Document是什么对象。四、正确解决方案一不要让对象变字符串最佳方案如果数据来源是 LangChain例如from langchain_core.documents import Document docs [ Document( metadata{ pk:12, page:2 }, page_content测试内容 ) ]此时print(type(docs))输出list里面元素print(type(docs[0]))输出Document那么直接for doc in docs: print(doc.metadata[page]) print(doc.page_content)输出2 测试内容五、真实场景数据库里面保存成字符串怎么办很多项目比如mysql 字段 documents 内容 [Document(...)]读取以后content row.documents变成str怎么办方法1正则提取 page_content如果只是想获取文本import re text Document(metadata{page:2}, page_contenthello world) contents re.findall( rpage_content(.*?), text, re.S ) print(contents)结果[ hello world ]然后result \n.join(contents)得到hello world六、方法2重新构造 Document 对象推荐在 RAG 项目中使用。假设字符串doc_str里面metadata page_content解析from langchain_core.documents import Document docs[] for item in解析后的数据: docs.append( Document( metadataitem[metadata], page_contentitem[page_content] ) )之后for doc in docs: print(doc.metadata[page]) print(doc.page_content)七、如果字符串格式固定可以使用 ast 转换例如text [ { metadata:{ page:2 }, page_content:hello } ] 转换import ast data ast.literal_eval(text) for item in data: print(item[metadata][page]) print(item[page_content])输出2 hello八、RAG项目中的实际应用在知识库系统里面流程PDF | ↓ Document对象 Document( metadata{ page:1 }, page_content政策内容 ) | ↓ Embedding | ↓ Vector DB检索回来应该保持List[Document]例如docs vector_store.similarity_search(question)返回[ Document(...), Document(...) ]然后for doc in docs: page doc.metadata[page] content doc.page_content生成引用来源 政策文件.pdf 第2页 内容 xxxx九、两个问题总结问题本质解决方案字符串 List 转 Liststr → listast.literal_eval()字符串 Document 转对象str → Document不要序列化或者重新构造获取 page读取 metadatadoc.metadata[page]获取文本读取 page_contentdoc.page_content十、最终记忆开发中遇到看起来像对象先问print(type(data))如果str不要直接data.xxx先恢复对象。RAG 开发尤其注意Document对象 ↓ 不要变成字符串 ↓ 保持 List[Document] ↓ metadata 保存来源 ↓ page_content 保存正文这也是为什么 LangChain、LlamaIndex 等框架一直强调检索阶段保持 Document 对象结构不要提前转成字符串。