You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PyQt5中如何正确存取list/dict/int等类型变量到本地文件

问题根因

原repr()逐行写txt的方案失效,核心是两个硬伤:

  • 读取逻辑只拿到了原始文本,没有做类型还原:readlines()返回的每一行都是纯字符串,还带末尾的换行符,直接把字符串赋值给原本是int/list/dict类型的变量,自然类型不匹配;如果直接对字符串做list转换,会把字符串逐字符拆成单个元素,就是出现的逐字符拆分异常。
  • 分隔符和内容冲突:用\n作为不同配置项的分隔符,但存的自定义代码本身就包含大量\n换行,写入时这些内置换行会把单个配置项拆成多行,读取时行索引完全错位,内容自然对不上,还会残留转义字符。
可行实现方案

pickle完全适用于当前PyQt5桌面应用场景,除此之外也可以根据需求选JSON方案,两种都比手写txt拼接可靠。

方案1:pickle序列化(实现成本最低,无转义问题)

pickle是Python标准库自带的二进制序列化工具,能直接还原int、list、dict、str等原生Python类型,不需要手动处理转义、换行问题,缺点是生成的文件是二进制格式,用户无法直接打开编辑。
存储代码:

import pickle

# 把所有配置项打包成字典,不需要手动拼换行
config = {
    "score": score,
    "ocount": ocount,
    "option": option,
    "option_ans": option_ans,
    "matchname": matchname,
    "scenario": scenario,
    "_Options": _Options,
    "_Optionselected": _Optionselected,
    "eInfo": eInfo,
    "sVar": sVar,
    "cusotm": cusotm,
    "survey1": survey1,
    "survey_ans": survey_ans,
    "eInfoName": eInfoName,
    "sVarName": sVarName,
    "tempcode": tempcode,
    "usercode": usercode
}

# 用二进制模式写入
with open(f"{configName}.pkl", "wb") as f:
    pickle.dump(config, f)

读取代码:

with open(f"{configName}.pkl", "rb") as f:
    config = pickle.load(f)

# 直接按键取值,类型和存储时完全一致,不需要额外转换
score = config["score"]
ocount = config["ocount"]
usercode = config["usercode"]
# 其余配置按相同方式取即可

注意:不要加载来源不可信的pickle文件,存在任意代码执行风险,仅加载自己应用生成的配置文件没有问题。

方案2:JSON存储(纯文本格式,支持人工编辑)

如果需要让用户可以直接打开配置文件手动修改,就用JSON格式,同样是Python标准库自带能力,当前用到的int、list、dict、str类型都在JSON的原生支持范围内,不会有兼容问题。
存储代码:

import json

config = {
    # 配置字典结构和pickle方案完全一致
    "score": score,
    "ocount": ocount,
    # 其余配置项同上
    "usercode": usercode
}

# 指定utf-8编码,ensure_ascii=False避免中文乱码,indent=4格式化输出方便阅读
with open(f"{configName}.json", "w", encoding="utf-8") as f:
    json.dump(config, f, ensure_ascii=False, indent=4)

读取代码:

with open(f"{configName}.json", "r", encoding="utf-8") as f:
    config = json.load(f)
# 按键取值即可,类型自动还原

临时兼容原txt方案的方法

如果一定要沿用txt存储格式,需要解决分隔符冲突和类型还原两个问题:

  1. 替换分隔符:用一个不会出现在用户代码里的特殊字符串(比如===CUSTOM_CONFIG_SPLIT_FLAG===)代替\n作为配置项分隔符
  2. 类型还原:读取到每个配置项的字符串后,用ast.literal_eval()做安全的字面量转换,不要直接用原始字符串,也不要用不安全的eval()
    示例代码:
import ast
SPLIT_FLAG = "===CUSTOM_CONFIG_SPLIT_FLAG==="

# 写入
with open(f"{configName}.txt", "w", encoding="utf-8") as f:
    write_content = SPLIT_FLAG.join([
        repr(score), repr(ocount), repr(option), repr(option_ans),
        repr(matchname), repr(scenario), repr(_Options), repr(_Optionselected),
        repr(eInfo), repr(sVar), repr(cusotm), repr(survey1), repr(survey_ans),
        repr(eInfoName), repr(sVarName), repr(tempcode), repr(usercode)
    ])
    f.write(write_content)

# 读取
with open(f"{configName}.txt", "r", encoding="utf-8") as f:
    raw_content = f.read()
raw_items = raw_content.split(SPLIT_FLAG)
tmp = [ast.literal_eval(item) for item in raw_items]
# 按写入顺序取值即可
score = tmp[0]
ocount = tmp[1]
usercode = tmp[-1]

该方案稳定性差,一旦分隔符出现在用户输入的代码或配置值里,就会出现解析错误,优先选择前两种方案。

内容的提问来源于stack exchange,提问作者SCH

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 07:12:28