Python注册功能加密密码时出现UnicodeEncodeError报错求解决方案
问题描述
开发模拟用户注册程序时,选择「创建账户」选项可将用户名密码存入对应txt文件,基础功能运行正常。新增维吉尼亚密码加密逻辑后运行程序触发编码错误,单独运行加密模块无异常。
报错信息
File "C:\Program\Files\WindowsApps\PythonSoftwareFoundation.Python.3.9_3.9.2032.0_x64__qbz5n2kfra8p0\lib\encodings\cp1252.py", line 19, in encode return codecs.charmap_encode(input,self.errors,encoding_table)[0] UnicodeEncodeError: 'charmap' codec can't encode character '\x95' in position 2: character maps to "undefined"
相关代码
业务代码
# coding: utf-8 import colorama from colorama import Fore, Back, Style import os import time import platform import shutil import sys import _socket import socket from Cryptage import * #------------------------------------------------------------------------------------------------- cle= open("cle.txt","r", encoding="utf-8") cle=cle.read() colorama.init(autoreset = True) Boucle = 1 Pseudo = "" encoded_string = '' #------------------------------------------------------------------------------------------------- def Clean(): if platform.system() == "Windows": os.system("cls") elif platform.system() == "Linux": os.system("clear") #------------------------------------------------------------------------------------------------- def Acceuil(): Clean() print(Fore.BLUE+"<===ACCEUIL===>") print(Fore.BLUE+"---------------------------------------------------------------------") print(Fore.BLUE+"1. Se connecter") print(Fore.BLUE+"2. S'inscrire") print(Fore.BLUE+"3. Quitter") print(Fore.BLUE+"---------------------------------------------------------------------") choix = input() if choix =='1': Connexion() elif choix =='2': Register() elif choix =='3': Clean() print("Fin du programme...") time.sleep(2.4) sys.exit() else: Clean() print(Fore.RED + "invalide") colorama.init(autoreset = True) #------------------------------------------------------------------------------------------------- def Register(): Clean() print(Fore.BLUE+"<===INSCRIPTION===>") print(Fore.BLUE+"---------------------------------------------------------------------") Pseudo, MDP = input(Fore.BLUE+"Pseudo, MDP: ").split() TxtUser = "{Pseudo2}.txt".format(Pseudo2=Pseudo) CheminBase = "C:\\Users\\yuris\\Desktop\\Python\\GestionDeCompte\\{TxtUser2}".format(TxtUser2=TxtUser) CheminArriver = "C:\\Users\\yuris\\Desktop\\Python\\GestionDeCompte\\Users\\{TxtUser2}".format(TxtUser2=TxtUser) MDPcrypted = encode(cle, MDP) if os.path.exists(CheminArriver): Clean() print(Fore.RED+"Le Pseudo",Fore.RED+Pseudo,Fore.RED+"Existe deja") input() else: NewUser = open(TxtUser,"x") NewUser.close() NewUser = open(TxtUser,"a") NewUser.write("Pseudo: ") NewUser.write(Pseudo) NewUser.write("! ") NewUser.write("MDP: ") NewUser.write( MDPcrypted) NewUser.write("!") NewUser.close() shutil.move(CheminBase,CheminArriver) print(Fore.BLUE+"Déplacement vers connexion...") time.sleep(2.4) Connexion() #------------------------------------------------------------------------------------------------- def Connexion(): Clean() print(Fore.BLUE+"<===CONNEXION===>") print(Fore.BLUE+"---------------------------------------------------------------------") Pseudo, MDP = input(Fore.BLUE+"Pseudo, MDP: ").split() print(Fore.BLUE+"---------------------------------------------------------------------") TxtUser = "{Pseudo2}.txt".format(Pseudo2=Pseudo) CheminArriver = "C:\\Users\\yuris\\Desktop\\Python\\GestionDeCompte\\Users\\{TxtUser2}".format(TxtUser2=TxtUser) if os.path.exists(CheminArriver) : MDPregister = "{MDP2}!".format(MDP2=MDP) UserConnect = open(CheminArriver,"r") for ligne in UserConnect: if MDPregister in ligne: MenuPrincipal() else: print(Fore.RED+"Le Pseudo ou le MDP est invalide") input() else: print(Fore.RED+"Le Pseudo ou le MDP est invalide") input() #------------------------------------------------------------------------------------------------- def MenuPrincipal(): while Boucle != 0: Clean() print(Fore.GREEN+"Bienvenue",Fore.GREEN+Pseudo) input() #------------------------------------------------------------------------------------------------- while Boucle != 0: Acceuil() print("")
加密模块代码(维吉尼亚密码实现)
# coding: utf-8 # vigenere cipher #-------------------------------------------------------------------------------- cle= open("cle.txt","r", encoding="utf-8") cle=cle.read() #-------------------------------------------------------------------------------- def encode(cle, string): encoded_chars = [] for i in range(len(string)): key_c =cle[i % len(cle)] encoded_c = chr(ord(string[i]) + ord(key_c) % 256) encoded_chars.append(encoded_c) encoded_string = ''.join(encoded_chars) return encoded_string def decode(cle, string): encoded_chars = [] for i in range(len(string)): key_c = cle[i % len(cle)] encoded_c = chr((ord(string[i]) - ord(key_c) + 256) % 256) encoded_chars.append(encoded_c) encoded_string = ''.join(encoded_chars) return encoded_string
报错原因
- Windows系统下Python的
open()函数默认使用系统默认编码(此处为cp1252编码)操作文件,你实现的维吉尼亚加密会生成0-255区间的单字节字符,其中部分字符不存在cp1252的编码映射表,写入文件触发编码转换失败。 - 单独运行加密模块无异常是因为仅在内存中处理字符串,没有触发写入文件的编码转换步骤。
解决方案
方案1:指定文件编码为latin-1
latin-1编码支持所有0-255区间的单字节字符,完全匹配加密后的输出格式,修改所有文件操作的open()语句,显式指定编码:
- 创建用户文件:
NewUser = open(TxtUser,"x", encoding="latin-1") - 写入用户信息:
NewUser = open(TxtUser,"a", encoding="latin-1") - 读取用户文件校验登录:
UserConnect = open(CheminArriver,"r", encoding="latin-1")
方案2:加密结果转base64存储
将加密后的字符串转成base64格式的可打印字符再存储,完全避免编码兼容问题,适配所有系统环境:
- 引入base64模块:
import base64 - 写入加密密码前转换:
MDPcrypted = base64.b64encode(MDPcrypted.encode('latin-1')).decode('ascii') - 读取校验密码前先解码base64,再调用解密函数校验即可。
内容的提问来源于stack exchange,提问作者Silver Red
相关产品推荐
相关产品推荐

