Spyder5.2脚本运行正常调试时触发utf-8解码错误求助
问题基本信息
- 运行环境:Anaconda 发行版 Python 3.6,IDE 为 Spyder v5.2
- 异常表现:按 Run (F5) 可正常运行脚本无报错;按 Debug the file (Ctrl+F5) 启动调试时程序直接中断,抛出如下错误:
Traceback (most recent call last): File "C:\ProgramData\Anaconda3\envs\Python_v1\lib\tokenize.py", line 390, in find_cookie line_string = line.decode('utf-8') UnicodeDecodeError: 'utf-8' codec can't decode byte 0xed in position 22: invalid continuation byte During handling of the above exception, another exception occurred: File "<string>", line unknown SyntaxError: invalid or missing encoding declaration for 'c:\\users\\jruizguillen\\xxxxxxxx xx\\xxxxxxxxx xx xxxxx x xxxxxx\\xxxxxxxxxxxx xxxxxxxx\\xxxxxxxx\\xxx xxxxxxxxxxxxxxxxxxx\\actualizar_tabla_disp_real_mtd.py'
已尝试的无效操作
- 移除代码中所有重音符号、特殊字符
- 将代码复制到全新空白文件保存
- 在文件头部添加编码声明
# -*- coding:ISO-8859-1-*-,修改Python全局编码配置
以上操作均无法解决问题。
涉及的完整业务代码
import mysql.connector import os, os.path from datetime import datetime import pandas as pd # Conexion con la base de datos miConexion = mysql.connector.connect( host='111.11.111.11', user= 'user', passwd='whatever', db='database_data') lista_insert = list() deleted_files=0 # Se sacan las horas de cada mes cur = miConexion.cursor() cur.execute("SELECT * FROM disponibildad_yte.mes") horas_mes = cur.fetchall() ###### Archivos enviados por las zonas ###### mes_declaracion_datos = input("Seleccione el ano y mes de declaracion de datos (AAAA-MM): ") # Seleccionamos el mes en el que las zonas han declarado los datos rutas_carpetas_meses = os.listdir(r"Envios zonas") # Carpetas de todos los meses en los que las zonas han declarado carpeta_elegida = list(filter(lambda x: mes_declaracion_datos in x, rutas_carpetas_meses)) # Carpeta donde se encuentran los datos declarados del mes seleccionado ruta_archivos = r"Envios zonas" + r"\\" + carpeta_elegida[0] # Ruta donde se encuentran los archivos que envian las zonas print ("\n" + "Los datos se van a extraer de la siguiente ruta: " + ruta_archivos + "\n") nombre_archivos = os.listdir (ruta_archivos) # Nombre de todos los archivos que se encuentran en esa carpeta print ("Los archivos encontrados en la ruta son: \n") for file in range (0, len (nombre_archivos)): if '.xlsx' in nombre_archivos[file-deleted_files]: print (nombre_archivos[file-deleted_files]) else: nombre_archivos.pop(file-deleted_files) deleted_files=deleted_files + 1 print ("\n" + "Iniciando extraccion de datos e insercion en base de datos: \n") # Version version = datetime.strptime(mes_declaracion_datos, "%Y-%m") # La version sera la del mes en que la zona ha declarado los datos # Borrar la BBDD si hay algun registro previo de la misma version delete_query="DELETE FROM disponibildad_yte.datos_indisp WHERE version = '%s'" %(version) cur.execute(delete_query) miConexion.commit() for zona in range (0, len (nombre_archivos)): archivo = 'Envios zonas/' + carpeta_elegida[0] + '/' + nombre_archivos[zona] df = pd.read_excel(archivo, sheet_name="Input", engine = 'openpyxl') for i in range (0, len(df)): #### Extraccion de datos en la excel e insercion en BBDD #### ## Extraccion de datos ## # Fecha de extraccion (Ano-Mes-Dia Hora:Minuto:Segundo) fecha_actualizacion = datetime.now().strftime("%Y-%m-%d %H:%M:%S") # ID de activo id_MOD = df["id_MOD"][i] # ID mes (Ano-Mes-Dia Hora:Minuto:Segundo) #id_mes = str(df["month"][i]) id_mes= (str(version.year)+'-'+str(df["month"][i])+'-01 00:00:00') # Familia familia = df["Family"][i] # Indisponibilidad (indisponibilidad por mes) if (str(df["Unavailability (monthly and asset)"][i]) == "nan"): # Si no han rellenado alguna celda de la columna de indisponibilidad la ponemos a 0, sino da error indisponibilidad = 0 else: indisponibilidad = float(df["Unavailability (monthly and asset)"][i]) # Horas de indisponibilidad #for j in range (0, len(horas_mes)): #if str(horas_mes[j][0].month) == datetime.strptime(id_mes,'%Y-%m-%d %H:%M:%S').month: #h = horas_mes[j][2] h = [tple[2] for tple in horas_mes if tple[0]== datetime.strptime(id_mes,'%Y-%m-%d %H:%M:%S')][0] #break horas_indisp = float(indisponibilidad*float(df["Power"][i])*h) # Se hace el calculo de horas de indisponibilidad (indisponibilidad*potencia del parque*horas del mes) valores = (fecha_actualizacion, id_MOD, id_mes, familia, indisponibilidad, horas_indisp, version) lista_insert.append(valores) insert_query = "INSERT INTO disponibildad_yte.datos_indisp (fecha_actualizacion, id_MOD, id_mes, familia, indisponibilidad, horas_indisp, version) VALUES (%s, %s, %s, %s, %s, %s, %s)" cur.executemany (insert_query, lista_insert) lista_insert.clear() miConexion.commit() print ("Datos de " + nombre_archivos[zona] + " extraidos e insertados en base de datos con exito \n") print ("ACTUALIZACION DE BASE DE DATOS COMPLETADA CON EXITO")
故障根因
报错和代码内容本身无关,问题出在脚本所在的完整文件路径包含非UTF-8编码的字符:
- F5直接运行时,Spyder调用系统默认编码解析文件路径,和Windows本地编码一致,不会触发解码错误
- Ctrl+F5调试模式下,Spyder内置的pdb调试组件会强制使用UTF-8编码解析待调试文件的全路径,报错里的
0xed字节就是西语重音字符的Latin-1编码值,无法被UTF-8正常解码,错误发生在tokenize模块读取文件路径阶段,还没走到读取代码内容、识别文件头部编码声明的步骤,所以修改代码内容、加头部编码声明都没用。
解决方法
- 优先选最稳妥的方案:把脚本文件移动到全英文、无特殊字符、无空格的纯ASCII路径下,比如直接放到
D:\work_scripts\这类简单路径,不要放在带重音字符、中文、特殊符号的用户个人目录下,再启动调试即可正常运行 - 备选方案:打开Spyder设置,依次进入
工具 -> 首选项 -> 调试器,找到调试器的默认文件编码配置项,将默认编码从UTF-8改为和系统匹配的本地编码(西语Windows系统通常为cp1252/ISO-8859-1),保存后重启Spyder即可 - 不要修改Python全局默认编码,会引发其他第三方库的编码兼容问题。
内容的提问来源于stack exchange,提问作者Javier
相关产品推荐
相关产品推荐

