错误 IndexError 加载文件配置
Error IndexError load file config
我的 class 配置中有一个函数可以加载配置文本文件。在加载数据之前,函数会检查文件以避免用户手动修改文件时出现故障。
def load_config(self):
list_dat = []
list_str = []
with open(self.path, "r") as file:
for conf in file:
conf = conf.replace(": ", "|")
conf = conf.replace("\n", "")
try:
conf1, conf2 = conf.split("|")
except ValueError:
self.new_config()
break
try:
conf2 = ast.literal_eval(conf2)
except (ValueError, SyntaxError):
self.new_config()
break
if isinstance(conf2, tuple):
self.new_config()
break
list_str.append(conf1)
list_dat.append(conf2)
for x in range(0, len(list_str)):
if list_str[x] != self.conf_str[x]:
self.change_config(list_str[x], self.conf_str[x], x, text=True)
list_str[x] = self.conf_str[x]
for y in range(0, len(list_dat)):
if type(list_dat[y]) != type(self.list_default[y]):
self.change_config(list_dat[y], self.list_default[y], y)
list_dat[y] = self.list_default[y]
if len(list_dat) == 0 and len(list_str) == 0:
self.new_config()
app = wx.App(False)
width, height = wx.GetDisplaySize()
if list_dat[1] != width:
if list_dat[1] == self.list_default[1]:
if list_dat[0] == False:
self.change_config(list_dat[1], width, 1)
self.change_config(list_dat[2], height, 2)
list_dat[1] = width
list_dat[2] = height
else:
self.change_config(list_dat[1], width, 1)
self.change_config(list_dat[2], height, 2)
list_dat[1] = width
list_dat[2] = height
if list_dat[2] != height:
if list_dat[2] == self.list_default[2]:
if list_dat[0] == False:
self.change_config(list_dat[1], width, 1)
self.change_config(list_dat[2], height, 2)
list_dat[1] = width
list_dat[2] = height
else:
self.change_config(list_dat[1], width, 1)
self.change_config(list_dat[2], height, 2)
list_dat[1] = width
list_dat[2] = height
if list_dat[4] > 100:
self.change_config(list_dat[4], 100, 4)
list_dat[4] = 100
else:
if list_dat[4] < 0:
self.change_config(list_dat[4], 0, 4)
list_dat[4] = 0
if list_dat[5] > 100:
self.change_config(list_dat[5], 100, 5)
list_dat[5] = 100
else:
if list_dat[5] < 0:
self.change_config(list_dat[5], 0, 5)
list_dat[5] = 0
if list_dat[6] > 100:
self.change_config(list_dat[6], 100, 6)
list_dat[6] = 100
else:
if list_dat[6] < 0:
self.change_config(list_dat[6], 0, 6)
list_dat[6] = 0
if list_dat[7] > 100:
self.change_config(list_dat[7], 100, 7)
list_dat[7] = 100
else:
if list_dat[7] < 0:
self.change_config(list_dat[7], 0, 7)
list_dat[7] = 0
if list_dat[8] > 100:
self.change_config(list_dat[8], 100, 8)
list_dat[8] = 100
else:
if list_dat[8] < 0:
self.change_config(list_dat[8], 0, 8)
list_dat[8] = 0
self.main.id[20], self.main.id[9] = list_dat[0], list_dat[3]
self.main.id[4], self.main.id[5] = list_dat[1], list_dat[2]
self.main.id[11], self.main.id[13], self.main.id[15], self.main.id[17], self.main.id[19] = list_dat[4], list_dat[5], list_dat[6], list_dat[7], list_dat[8]
def change_config(self, old, new, n, text=False):
with open(self.path, "r") as file:
temp = file.readlines()
if text:
temp1, temp2 = temp[n].split(": ")
temp1 = temp1.replace(str(old), str(new))
temp[n] = temp1 + ": " + temp2
else:
temp[n] = temp[n].replace(str(old), str(new))
with open(self.path, "w") as file:
file.writelines(temp)
相反,这是配置文件:
Display Set: True
Display Width: 1024
Display Height: 576
Fullscreen: False
Music Volume: 50
Sound Volume: 50
Voice Volume: 50
Ambient Volume: 50
Other Volume: 50
现在,我收到一个错误,老实说,我无法理解是什么原因造成的。例如,如果我以这种方式更改文件:
Display Set: True
Display Width: gfgfdd
Display Height: 576
Fullscreen: False
Music Volume: 50
Sound Volume: 50
Voice Volume: 50
Ambient Volume: 50
Other Volume: 50
我收到错误:
if list_dat[4] > 100:
IndexError: list index out of range
如果我更改 Display Height
、Music Volume
、Sound Volume
、Voice Volume
、Ambient Volume
和 Other Volume
.[=46,也会发生同样的事情=]
报错后,我去查看配置文件,发现已经正确修改了。这就是为什么我不明白为什么我总是收到这些错误。
一直给我错误的块是:
if list_dat[1] != width:
if list_dat[1] == self.list_default[1]:
if list_dat[0] == False:
self.change_config(list_dat[1], width, 1)
self.change_config(list_dat[2], height, 2)
list_dat[1] = width
list_dat[2] = height
else:
self.change_config(list_dat[1], width, 1)
self.change_config(list_dat[2], height, 2)
list_dat[1] = width
list_dat[2] = height
if list_dat[2] != height:
if list_dat[2] == self.list_default[2]:
if list_dat[0] == False:
self.change_config(list_dat[1], width, 1)
self.change_config(list_dat[2], height, 2)
list_dat[1] = width
list_dat[2] = height
else:
self.change_config(list_dat[1], width, 1)
self.change_config(list_dat[2], height, 2)
list_dat[1] = width
list_dat[2] = height
if list_dat[4] > 100:
self.change_config(list_dat[4], 100, 4)
list_dat[4] = 100
else:
if list_dat[4] < 0:
self.change_config(list_dat[4], 0, 4)
list_dat[4] = 0
if list_dat[5] > 100:
self.change_config(list_dat[5], 100, 5)
list_dat[5] = 100
else:
if list_dat[5] < 0:
self.change_config(list_dat[5], 0, 5)
list_dat[5] = 0
if list_dat[6] > 100:
self.change_config(list_dat[6], 100, 6)
list_dat[6] = 100
else:
if list_dat[6] < 0:
self.change_config(list_dat[6], 0, 6)
list_dat[6] = 0
if list_dat[7] > 100:
self.change_config(list_dat[7], 100, 7)
list_dat[7] = 100
else:
if list_dat[7] < 0:
self.change_config(list_dat[7], 0, 7)
list_dat[7] = 0
if list_dat[8] > 100:
self.change_config(list_dat[8], 100, 8)
list_dat[8] = 100
else:
if list_dat[8] < 0:
self.change_config(list_dat[8], 0, 8)
list_dat[8] = 0
你能帮帮我吗?
编辑:
我添加了一个简化的 class 版本,只有错误所需的功能。
import ast, os, wx
from pathlib import Path
class config_lib():
def __init__(self):
# IdDataDefaultConfig
self.id1 = True # SetDisplayDefault
self.id2 = 1024 # DisplayWidthDefault
self.id3 = 576 # DisplayHeightDefault
self.id4 = 1024 # DisplayWidthUser
self.id5 = 576 # DisplayHeightUser
self.id6 = 0 # LocationDisplayX
self.id7 = 50 # LocationDisplayY
self.id8 = False # FullscreenDefault
self.id9 = False # FullscreenUser
self.id10 = 50 # MusicVolumeDefault
self.id11 = 50 # MusicVolumeUser
self.id12 = 50 # SoundVolumeDefault
self.id13 = 50 # SoundVolumeUser
self.id14 = 50 # VoiceVolumeDefault
self.id15 = 50 # VoiceVolumeUser
self.id16 = 50 # AmbientVolumeDefault
self.id17 = 50 # AmbientVolumeUser
self.id18 = 50 # OtherAudioVolumeDefault
self.id19 = 50 # OtherAudioVolumeUser
self.id20 = True # SetDisplayUser
self.conf_str = ["Display Set", "Display Width", "Display Height", "Fullscreen", "Music Volume", "Sound Volume", "Voice Volume", "Ambient Volume", "Other Volume"]
self.list_default = [self.id1, self.id2, self.id3, self.id8, self.id10, self.id12, self.id14, self.id16, self.id18]
self.path = os.path.join("dat.bw3")
self.conf = Path(self.path)
try:
lc = self.conf.resolve()
except FileNotFoundError:
self.new_config()
else:
self.load_config()
def new_config(self):
list_dat = [[self.conf_str[0], self.id1], [self.conf_str[1], self.id2], [self.conf_str[2], self.id3], [self.conf_str[3], self.id8], [self.conf_str[4], self.id10], [self.conf_str[5], self.id12], [self.conf_str[6], self.id14], [self.conf_str[7], self.id16], [self.conf_str[8], self.id18]]
with open(self.path, "wt") as file:
for conf in list_dat:
print(conf[0], conf[1], sep=': ', file=file)
self.load_config()
def load_config(self):
list_dat = []
list_str = []
with open(self.path, "r") as file:
for conf in file:
conf = conf.replace(": ", "|")
conf = conf.replace("\n", "")
try:
conf1, conf2 = conf.split("|")
except ValueError:
self.new_config()
break
try:
conf2 = ast.literal_eval(conf2)
except (ValueError, SyntaxError):
self.new_config()
break
if isinstance(conf2, tuple):
self.new_config()
break
list_str.append(conf1)
list_dat.append(conf2)
for x in range(0, len(list_str)):
if list_str[x] != self.conf_str[x]:
self.change_config(list_str[x], self.conf_str[x], x, text=True)
list_str[x] = self.conf_str[x]
for y in range(0, len(list_dat)):
if type(list_dat[y]) != type(self.list_default[y]):
self.change_config(list_dat[y], self.list_default[y], y)
list_dat[y] = self.list_default[y]
if len(list_dat) == 0 and len(list_str) == 0:
self.new_config()
app = wx.App(False)
width, height = wx.GetDisplaySize()
if list_dat[1] != width:
if list_dat[1] == self.list_default[1]:
if list_dat[0] == False:
self.change_config(list_dat[1], width, 1)
self.change_config(list_dat[2], height, 2)
list_dat[1] = width
list_dat[2] = height
else:
self.change_config(list_dat[1], width, 1)
self.change_config(list_dat[2], height, 2)
list_dat[1] = width
list_dat[2] = height
if list_dat[2] != height:
if list_dat[2] == self.list_default[2]:
if list_dat[0] == False:
self.change_config(list_dat[1], width, 1)
self.change_config(list_dat[2], height, 2)
list_dat[1] = width
list_dat[2] = height
else:
self.change_config(list_dat[1], width, 1)
self.change_config(list_dat[2], height, 2)
list_dat[1] = width
list_dat[2] = height
if list_dat[4] > 100:
self.change_config(list_dat[4], 100, 4)
list_dat[4] = 100
else:
if list_dat[4] < 0:
self.change_config(list_dat[4], 0, 4)
list_dat[4] = 0
if list_dat[5] > 100:
self.change_config(list_dat[5], 100, 5)
list_dat[5] = 100
else:
if list_dat[5] < 0:
self.change_config(list_dat[5], 0, 5)
list_dat[5] = 0
if list_dat[6] > 100:
self.change_config(list_dat[6], 100, 6)
list_dat[6] = 100
else:
if list_dat[6] < 0:
self.change_config(list_dat[6], 0, 6)
list_dat[6] = 0
if list_dat[7] > 100:
self.change_config(list_dat[7], 100, 7)
list_dat[7] = 100
else:
if list_dat[7] < 0:
self.change_config(list_dat[7], 0, 7)
list_dat[7] = 0
if list_dat[8] > 100:
self.change_config(list_dat[8], 100, 8)
list_dat[8] = 100
else:
if list_dat[8] < 0:
self.change_config(list_dat[8], 0, 8)
list_dat[8] = 0
self.id20, self.id9 = list_dat[0], list_dat[3]
self.id4, self.id5 = list_dat[1], list_dat[2]
self.id11, self.id13, self.id15, self.id17, self.id19 = list_dat[4], list_dat[5], list_dat[6], list_dat[7], list_dat[8]
def change_config(self, old, new, n, text=False):
with open(self.path, "r") as file:
temp = file.readlines()
if text:
temp1, temp2 = temp[n].split(": ")
temp1 = temp1.replace(str(old), str(new))
temp[n] = temp1 + ": " + temp2
else:
temp[n] = temp[n].replace(str(old), str(new))
with open(self.path, "w") as file:
file.writelines(temp)
conf = config_lib()
编辑 2:
在class的__init__
中,检查文件是否存在。如果不存在,则调用 new_config()
函数,它使用默认数据创建一个新文件,然后调用 load_config()
函数。如果文件存在,则直接调用 load_config()
函数。
load_config()
函数必须在将文件数据加载到程序之前检查文件数据。
load_config()
函数的第一块:
首先要做的是将文件中写入的内容转换为程序可以处理的内容。然后读取文件,将每一行(“:”)替换为以后有用的符号(“|”),并删除回车 return。现在我们必须将它一分为二,这样一边是数据的名称,而另一边是数据本身。这是通过划分先前插入符号(“|”)的位置来完成的。这个划分是在 try
中完成的,因此如果文件内部有一些错误,则通过使用 new_config()
创建一个新文件来覆盖该文件。第二件事是将数据(当前是字符串)转换为有效数据。这是由 ast.literal_eval()
完成的。出于与之前相同的原因,再次将所有内容放入 try
。最后,检查数据是单一的而不是元组。在list_dat
和list_str
中分别输入数据名称和数据。
load_config()
函数的第二个块:
首先要做的是检查,一个默认的名字列表,如果数据的名字是正确的,如果是错误的,就更正。数据相同,但在这种情况下,会检查类型是否与其默认对应类型相同。很少(例如 100 分之一),我注意到如果文件为空,则 split()
块或 ast.literal_eval()
块不会引发 Except
。所以我补充说:
if len(list_dat) == 0 and len(list_str) == 0:
self.new_config()
为了避免这个问题。
load_config()
函数的第三个块(这是给我问题的块):
检查屏幕的宽度和高度是否与数据的宽度和高度相同。如果它们不相等,则检查数据是否与默认值 (1024, 576) 相同。如果相同,最后检查默认加载模式为false。执行此检查是为了在创建程序屏幕时没有任何问题。如果这些检查中的任何一个失败(否则),宽度和高度数据将更改为默认数据。
if list_dat[1] != width:
if list_dat[1] == self.list_default[1]:
if list_dat[0] == False:
self.change_config(list_dat[1], width, 1)
self.change_config(list_dat[2], height, 2)
list_dat[1] = width
list_dat[2] = height
else:
self.change_config(list_dat[1], width, 1)
self.change_config(list_dat[2], height, 2)
list_dat[1] = width
list_dat[2] = height
if list_dat[2] != height:
if list_dat[2] == self.list_default[2]:
if list_dat[0] == False:
self.change_config(list_dat[1], width, 1)
self.change_config(list_dat[2], height, 2)
list_dat[1] = width
list_dat[2] = height
else:
self.change_config(list_dat[1], width, 1)
self.change_config(list_dat[2], height, 2)
list_dat[1] = width
list_dat[2] = height
同样进行音量控制,唯一不同的是数字不超过100(最大音量)或小于0(最小音量)。
if list_dat[4] > 100:
self.change_config(list_dat[4], 100, 4)
list_dat[4] = 100
else:
if list_dat[4] < 0:
self.change_config(list_dat[4], 0, 4)
list_dat[4] = 0
if list_dat[5] > 100:
self.change_config(list_dat[5], 100, 5)
list_dat[5] = 100
else:
if list_dat[5] < 0:
self.change_config(list_dat[5], 0, 5)
list_dat[5] = 0
if list_dat[6] > 100:
self.change_config(list_dat[6], 100, 6)
list_dat[6] = 100
else:
if list_dat[6] < 0:
self.change_config(list_dat[6], 0, 6)
list_dat[6] = 0
if list_dat[7] > 100:
self.change_config(list_dat[7], 100, 7)
list_dat[7] = 100
else:
if list_dat[7] < 0:
self.change_config(list_dat[7], 0, 7)
list_dat[7] = 0
if list_dat[8] > 100:
self.change_config(list_dat[8], 100, 8)
list_dat[8] = 100
else:
if list_dat[8] < 0:
self.change_config(list_dat[8], 0, 8)
list_dat[8] = 0
load_config()
函数的第四块:
将受控数据分配给它们的变量,供程序使用。
编辑 3:
很遗憾,我之前忘记说些什么了。我知道在 ast.literal_eval()
上会引发异常,这就是我将其放在 try
中的原因。发生这种情况时,将调用 new_config()
函数并且循环应该重新开始。因此列表 return 为空,并由支票再次填充。至少理论上是这样。取而代之的是,虽然文件是按应有的方式创建的(使用默认数据),但该函数的其余部分在第二次执行时会变得支离破碎。同样是因为错误仅由我输入的数据引起。对于其他的(Fullscreen etc.)有布尔值并且在第三块没有控制的,不会出现这个问题。
将你的脚本简化成这样后,
import ast
with open(self.path, "r") as file:
for conf in file:
conf = conf.replace(": ", "|")
conf = conf.replace("\n", "")
conf1, conf2 = conf.split("|")
conf2 = ast.literal_eval(conf2)
print(conf2)
很明显 ast.literal_eval() 方法抛出 ValueError 异常:
Traceback (most recent call last):
File "/usr/local/Cellar/python3/3.6.3/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/IPython/core/interactiveshell.py", line 2910, in run_code
exec(code_obj, self.user_global_ns, self.user_ns)
File "<ipython-input-214-f993e6585bcd>", line 7, in <module>
conf2 = ast.literal_eval(conf2)
File "/usr/local/Cellar/python3/3.6.3/Frameworks/Python.framework/Versions/3.6/lib/python3.6/ast.py", line 85, in literal_eval
return _convert(node_or_string)
File "/usr/local/Cellar/python3/3.6.3/Frameworks/Python.framework/Versions/3.6/lib/python3.6/ast.py", line 84, in _convert
raise ValueError('malformed node or string: ' + repr(node))
ValueError: malformed node or string: <_ast.Name object at 0x111f50f28>
既然你在这里处理它:
try:
conf2 = ast.literal_eval(conf2)
except (ValueError, SyntaxError):
self.new_config()
break
您得到的配置条目比预期少,因此 InvalidIndex
错误。
现在 ast.literal_eval()
抛出异常,因为您的输入无法评估为任何已知的 python 类型或方法。
请查看the docs以了解如何正确使用它
我的 class 配置中有一个函数可以加载配置文本文件。在加载数据之前,函数会检查文件以避免用户手动修改文件时出现故障。
def load_config(self):
list_dat = []
list_str = []
with open(self.path, "r") as file:
for conf in file:
conf = conf.replace(": ", "|")
conf = conf.replace("\n", "")
try:
conf1, conf2 = conf.split("|")
except ValueError:
self.new_config()
break
try:
conf2 = ast.literal_eval(conf2)
except (ValueError, SyntaxError):
self.new_config()
break
if isinstance(conf2, tuple):
self.new_config()
break
list_str.append(conf1)
list_dat.append(conf2)
for x in range(0, len(list_str)):
if list_str[x] != self.conf_str[x]:
self.change_config(list_str[x], self.conf_str[x], x, text=True)
list_str[x] = self.conf_str[x]
for y in range(0, len(list_dat)):
if type(list_dat[y]) != type(self.list_default[y]):
self.change_config(list_dat[y], self.list_default[y], y)
list_dat[y] = self.list_default[y]
if len(list_dat) == 0 and len(list_str) == 0:
self.new_config()
app = wx.App(False)
width, height = wx.GetDisplaySize()
if list_dat[1] != width:
if list_dat[1] == self.list_default[1]:
if list_dat[0] == False:
self.change_config(list_dat[1], width, 1)
self.change_config(list_dat[2], height, 2)
list_dat[1] = width
list_dat[2] = height
else:
self.change_config(list_dat[1], width, 1)
self.change_config(list_dat[2], height, 2)
list_dat[1] = width
list_dat[2] = height
if list_dat[2] != height:
if list_dat[2] == self.list_default[2]:
if list_dat[0] == False:
self.change_config(list_dat[1], width, 1)
self.change_config(list_dat[2], height, 2)
list_dat[1] = width
list_dat[2] = height
else:
self.change_config(list_dat[1], width, 1)
self.change_config(list_dat[2], height, 2)
list_dat[1] = width
list_dat[2] = height
if list_dat[4] > 100:
self.change_config(list_dat[4], 100, 4)
list_dat[4] = 100
else:
if list_dat[4] < 0:
self.change_config(list_dat[4], 0, 4)
list_dat[4] = 0
if list_dat[5] > 100:
self.change_config(list_dat[5], 100, 5)
list_dat[5] = 100
else:
if list_dat[5] < 0:
self.change_config(list_dat[5], 0, 5)
list_dat[5] = 0
if list_dat[6] > 100:
self.change_config(list_dat[6], 100, 6)
list_dat[6] = 100
else:
if list_dat[6] < 0:
self.change_config(list_dat[6], 0, 6)
list_dat[6] = 0
if list_dat[7] > 100:
self.change_config(list_dat[7], 100, 7)
list_dat[7] = 100
else:
if list_dat[7] < 0:
self.change_config(list_dat[7], 0, 7)
list_dat[7] = 0
if list_dat[8] > 100:
self.change_config(list_dat[8], 100, 8)
list_dat[8] = 100
else:
if list_dat[8] < 0:
self.change_config(list_dat[8], 0, 8)
list_dat[8] = 0
self.main.id[20], self.main.id[9] = list_dat[0], list_dat[3]
self.main.id[4], self.main.id[5] = list_dat[1], list_dat[2]
self.main.id[11], self.main.id[13], self.main.id[15], self.main.id[17], self.main.id[19] = list_dat[4], list_dat[5], list_dat[6], list_dat[7], list_dat[8]
def change_config(self, old, new, n, text=False):
with open(self.path, "r") as file:
temp = file.readlines()
if text:
temp1, temp2 = temp[n].split(": ")
temp1 = temp1.replace(str(old), str(new))
temp[n] = temp1 + ": " + temp2
else:
temp[n] = temp[n].replace(str(old), str(new))
with open(self.path, "w") as file:
file.writelines(temp)
相反,这是配置文件:
Display Set: True
Display Width: 1024
Display Height: 576
Fullscreen: False
Music Volume: 50
Sound Volume: 50
Voice Volume: 50
Ambient Volume: 50
Other Volume: 50
现在,我收到一个错误,老实说,我无法理解是什么原因造成的。例如,如果我以这种方式更改文件:
Display Set: True
Display Width: gfgfdd
Display Height: 576
Fullscreen: False
Music Volume: 50
Sound Volume: 50
Voice Volume: 50
Ambient Volume: 50
Other Volume: 50
我收到错误:
if list_dat[4] > 100:
IndexError: list index out of range
如果我更改 Display Height
、Music Volume
、Sound Volume
、Voice Volume
、Ambient Volume
和 Other Volume
.[=46,也会发生同样的事情=]
报错后,我去查看配置文件,发现已经正确修改了。这就是为什么我不明白为什么我总是收到这些错误。
一直给我错误的块是:
if list_dat[1] != width:
if list_dat[1] == self.list_default[1]:
if list_dat[0] == False:
self.change_config(list_dat[1], width, 1)
self.change_config(list_dat[2], height, 2)
list_dat[1] = width
list_dat[2] = height
else:
self.change_config(list_dat[1], width, 1)
self.change_config(list_dat[2], height, 2)
list_dat[1] = width
list_dat[2] = height
if list_dat[2] != height:
if list_dat[2] == self.list_default[2]:
if list_dat[0] == False:
self.change_config(list_dat[1], width, 1)
self.change_config(list_dat[2], height, 2)
list_dat[1] = width
list_dat[2] = height
else:
self.change_config(list_dat[1], width, 1)
self.change_config(list_dat[2], height, 2)
list_dat[1] = width
list_dat[2] = height
if list_dat[4] > 100:
self.change_config(list_dat[4], 100, 4)
list_dat[4] = 100
else:
if list_dat[4] < 0:
self.change_config(list_dat[4], 0, 4)
list_dat[4] = 0
if list_dat[5] > 100:
self.change_config(list_dat[5], 100, 5)
list_dat[5] = 100
else:
if list_dat[5] < 0:
self.change_config(list_dat[5], 0, 5)
list_dat[5] = 0
if list_dat[6] > 100:
self.change_config(list_dat[6], 100, 6)
list_dat[6] = 100
else:
if list_dat[6] < 0:
self.change_config(list_dat[6], 0, 6)
list_dat[6] = 0
if list_dat[7] > 100:
self.change_config(list_dat[7], 100, 7)
list_dat[7] = 100
else:
if list_dat[7] < 0:
self.change_config(list_dat[7], 0, 7)
list_dat[7] = 0
if list_dat[8] > 100:
self.change_config(list_dat[8], 100, 8)
list_dat[8] = 100
else:
if list_dat[8] < 0:
self.change_config(list_dat[8], 0, 8)
list_dat[8] = 0
你能帮帮我吗?
编辑:
我添加了一个简化的 class 版本,只有错误所需的功能。
import ast, os, wx
from pathlib import Path
class config_lib():
def __init__(self):
# IdDataDefaultConfig
self.id1 = True # SetDisplayDefault
self.id2 = 1024 # DisplayWidthDefault
self.id3 = 576 # DisplayHeightDefault
self.id4 = 1024 # DisplayWidthUser
self.id5 = 576 # DisplayHeightUser
self.id6 = 0 # LocationDisplayX
self.id7 = 50 # LocationDisplayY
self.id8 = False # FullscreenDefault
self.id9 = False # FullscreenUser
self.id10 = 50 # MusicVolumeDefault
self.id11 = 50 # MusicVolumeUser
self.id12 = 50 # SoundVolumeDefault
self.id13 = 50 # SoundVolumeUser
self.id14 = 50 # VoiceVolumeDefault
self.id15 = 50 # VoiceVolumeUser
self.id16 = 50 # AmbientVolumeDefault
self.id17 = 50 # AmbientVolumeUser
self.id18 = 50 # OtherAudioVolumeDefault
self.id19 = 50 # OtherAudioVolumeUser
self.id20 = True # SetDisplayUser
self.conf_str = ["Display Set", "Display Width", "Display Height", "Fullscreen", "Music Volume", "Sound Volume", "Voice Volume", "Ambient Volume", "Other Volume"]
self.list_default = [self.id1, self.id2, self.id3, self.id8, self.id10, self.id12, self.id14, self.id16, self.id18]
self.path = os.path.join("dat.bw3")
self.conf = Path(self.path)
try:
lc = self.conf.resolve()
except FileNotFoundError:
self.new_config()
else:
self.load_config()
def new_config(self):
list_dat = [[self.conf_str[0], self.id1], [self.conf_str[1], self.id2], [self.conf_str[2], self.id3], [self.conf_str[3], self.id8], [self.conf_str[4], self.id10], [self.conf_str[5], self.id12], [self.conf_str[6], self.id14], [self.conf_str[7], self.id16], [self.conf_str[8], self.id18]]
with open(self.path, "wt") as file:
for conf in list_dat:
print(conf[0], conf[1], sep=': ', file=file)
self.load_config()
def load_config(self):
list_dat = []
list_str = []
with open(self.path, "r") as file:
for conf in file:
conf = conf.replace(": ", "|")
conf = conf.replace("\n", "")
try:
conf1, conf2 = conf.split("|")
except ValueError:
self.new_config()
break
try:
conf2 = ast.literal_eval(conf2)
except (ValueError, SyntaxError):
self.new_config()
break
if isinstance(conf2, tuple):
self.new_config()
break
list_str.append(conf1)
list_dat.append(conf2)
for x in range(0, len(list_str)):
if list_str[x] != self.conf_str[x]:
self.change_config(list_str[x], self.conf_str[x], x, text=True)
list_str[x] = self.conf_str[x]
for y in range(0, len(list_dat)):
if type(list_dat[y]) != type(self.list_default[y]):
self.change_config(list_dat[y], self.list_default[y], y)
list_dat[y] = self.list_default[y]
if len(list_dat) == 0 and len(list_str) == 0:
self.new_config()
app = wx.App(False)
width, height = wx.GetDisplaySize()
if list_dat[1] != width:
if list_dat[1] == self.list_default[1]:
if list_dat[0] == False:
self.change_config(list_dat[1], width, 1)
self.change_config(list_dat[2], height, 2)
list_dat[1] = width
list_dat[2] = height
else:
self.change_config(list_dat[1], width, 1)
self.change_config(list_dat[2], height, 2)
list_dat[1] = width
list_dat[2] = height
if list_dat[2] != height:
if list_dat[2] == self.list_default[2]:
if list_dat[0] == False:
self.change_config(list_dat[1], width, 1)
self.change_config(list_dat[2], height, 2)
list_dat[1] = width
list_dat[2] = height
else:
self.change_config(list_dat[1], width, 1)
self.change_config(list_dat[2], height, 2)
list_dat[1] = width
list_dat[2] = height
if list_dat[4] > 100:
self.change_config(list_dat[4], 100, 4)
list_dat[4] = 100
else:
if list_dat[4] < 0:
self.change_config(list_dat[4], 0, 4)
list_dat[4] = 0
if list_dat[5] > 100:
self.change_config(list_dat[5], 100, 5)
list_dat[5] = 100
else:
if list_dat[5] < 0:
self.change_config(list_dat[5], 0, 5)
list_dat[5] = 0
if list_dat[6] > 100:
self.change_config(list_dat[6], 100, 6)
list_dat[6] = 100
else:
if list_dat[6] < 0:
self.change_config(list_dat[6], 0, 6)
list_dat[6] = 0
if list_dat[7] > 100:
self.change_config(list_dat[7], 100, 7)
list_dat[7] = 100
else:
if list_dat[7] < 0:
self.change_config(list_dat[7], 0, 7)
list_dat[7] = 0
if list_dat[8] > 100:
self.change_config(list_dat[8], 100, 8)
list_dat[8] = 100
else:
if list_dat[8] < 0:
self.change_config(list_dat[8], 0, 8)
list_dat[8] = 0
self.id20, self.id9 = list_dat[0], list_dat[3]
self.id4, self.id5 = list_dat[1], list_dat[2]
self.id11, self.id13, self.id15, self.id17, self.id19 = list_dat[4], list_dat[5], list_dat[6], list_dat[7], list_dat[8]
def change_config(self, old, new, n, text=False):
with open(self.path, "r") as file:
temp = file.readlines()
if text:
temp1, temp2 = temp[n].split(": ")
temp1 = temp1.replace(str(old), str(new))
temp[n] = temp1 + ": " + temp2
else:
temp[n] = temp[n].replace(str(old), str(new))
with open(self.path, "w") as file:
file.writelines(temp)
conf = config_lib()
编辑 2:
在class的__init__
中,检查文件是否存在。如果不存在,则调用 new_config()
函数,它使用默认数据创建一个新文件,然后调用 load_config()
函数。如果文件存在,则直接调用 load_config()
函数。
load_config()
函数必须在将文件数据加载到程序之前检查文件数据。
load_config()
函数的第一块:
首先要做的是将文件中写入的内容转换为程序可以处理的内容。然后读取文件,将每一行(“:”)替换为以后有用的符号(“|”),并删除回车 return。现在我们必须将它一分为二,这样一边是数据的名称,而另一边是数据本身。这是通过划分先前插入符号(“|”)的位置来完成的。这个划分是在 try
中完成的,因此如果文件内部有一些错误,则通过使用 new_config()
创建一个新文件来覆盖该文件。第二件事是将数据(当前是字符串)转换为有效数据。这是由 ast.literal_eval()
完成的。出于与之前相同的原因,再次将所有内容放入 try
。最后,检查数据是单一的而不是元组。在list_dat
和list_str
中分别输入数据名称和数据。
load_config()
函数的第二个块:
首先要做的是检查,一个默认的名字列表,如果数据的名字是正确的,如果是错误的,就更正。数据相同,但在这种情况下,会检查类型是否与其默认对应类型相同。很少(例如 100 分之一),我注意到如果文件为空,则 split()
块或 ast.literal_eval()
块不会引发 Except
。所以我补充说:
if len(list_dat) == 0 and len(list_str) == 0:
self.new_config()
为了避免这个问题。
load_config()
函数的第三个块(这是给我问题的块):
检查屏幕的宽度和高度是否与数据的宽度和高度相同。如果它们不相等,则检查数据是否与默认值 (1024, 576) 相同。如果相同,最后检查默认加载模式为false。执行此检查是为了在创建程序屏幕时没有任何问题。如果这些检查中的任何一个失败(否则),宽度和高度数据将更改为默认数据。
if list_dat[1] != width:
if list_dat[1] == self.list_default[1]:
if list_dat[0] == False:
self.change_config(list_dat[1], width, 1)
self.change_config(list_dat[2], height, 2)
list_dat[1] = width
list_dat[2] = height
else:
self.change_config(list_dat[1], width, 1)
self.change_config(list_dat[2], height, 2)
list_dat[1] = width
list_dat[2] = height
if list_dat[2] != height:
if list_dat[2] == self.list_default[2]:
if list_dat[0] == False:
self.change_config(list_dat[1], width, 1)
self.change_config(list_dat[2], height, 2)
list_dat[1] = width
list_dat[2] = height
else:
self.change_config(list_dat[1], width, 1)
self.change_config(list_dat[2], height, 2)
list_dat[1] = width
list_dat[2] = height
同样进行音量控制,唯一不同的是数字不超过100(最大音量)或小于0(最小音量)。
if list_dat[4] > 100:
self.change_config(list_dat[4], 100, 4)
list_dat[4] = 100
else:
if list_dat[4] < 0:
self.change_config(list_dat[4], 0, 4)
list_dat[4] = 0
if list_dat[5] > 100:
self.change_config(list_dat[5], 100, 5)
list_dat[5] = 100
else:
if list_dat[5] < 0:
self.change_config(list_dat[5], 0, 5)
list_dat[5] = 0
if list_dat[6] > 100:
self.change_config(list_dat[6], 100, 6)
list_dat[6] = 100
else:
if list_dat[6] < 0:
self.change_config(list_dat[6], 0, 6)
list_dat[6] = 0
if list_dat[7] > 100:
self.change_config(list_dat[7], 100, 7)
list_dat[7] = 100
else:
if list_dat[7] < 0:
self.change_config(list_dat[7], 0, 7)
list_dat[7] = 0
if list_dat[8] > 100:
self.change_config(list_dat[8], 100, 8)
list_dat[8] = 100
else:
if list_dat[8] < 0:
self.change_config(list_dat[8], 0, 8)
list_dat[8] = 0
load_config()
函数的第四块:
将受控数据分配给它们的变量,供程序使用。
编辑 3:
很遗憾,我之前忘记说些什么了。我知道在 ast.literal_eval()
上会引发异常,这就是我将其放在 try
中的原因。发生这种情况时,将调用 new_config()
函数并且循环应该重新开始。因此列表 return 为空,并由支票再次填充。至少理论上是这样。取而代之的是,虽然文件是按应有的方式创建的(使用默认数据),但该函数的其余部分在第二次执行时会变得支离破碎。同样是因为错误仅由我输入的数据引起。对于其他的(Fullscreen etc.)有布尔值并且在第三块没有控制的,不会出现这个问题。
将你的脚本简化成这样后,
import ast
with open(self.path, "r") as file:
for conf in file:
conf = conf.replace(": ", "|")
conf = conf.replace("\n", "")
conf1, conf2 = conf.split("|")
conf2 = ast.literal_eval(conf2)
print(conf2)
很明显 ast.literal_eval() 方法抛出 ValueError 异常:
Traceback (most recent call last):
File "/usr/local/Cellar/python3/3.6.3/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/IPython/core/interactiveshell.py", line 2910, in run_code
exec(code_obj, self.user_global_ns, self.user_ns)
File "<ipython-input-214-f993e6585bcd>", line 7, in <module>
conf2 = ast.literal_eval(conf2)
File "/usr/local/Cellar/python3/3.6.3/Frameworks/Python.framework/Versions/3.6/lib/python3.6/ast.py", line 85, in literal_eval
return _convert(node_or_string)
File "/usr/local/Cellar/python3/3.6.3/Frameworks/Python.framework/Versions/3.6/lib/python3.6/ast.py", line 84, in _convert
raise ValueError('malformed node or string: ' + repr(node))
ValueError: malformed node or string: <_ast.Name object at 0x111f50f28>
既然你在这里处理它:
try:
conf2 = ast.literal_eval(conf2)
except (ValueError, SyntaxError):
self.new_config()
break
您得到的配置条目比预期少,因此 InvalidIndex
错误。
现在 ast.literal_eval()
抛出异常,因为您的输入无法评估为任何已知的 python 类型或方法。
请查看the docs以了解如何正确使用它