【发布时间】:2022-06-22 22:10:17
【问题描述】:
在我的(简化的)脚本中,我有以下内容:
def predict(new_data):
.
.
.
model_list = fetch_needed_models() # ["f1","f2","f3"]
for m in model_list:
with open(f"./{m}.pkl","rb") as file:
exec(f"{m}=pickle.load(file)")
print(dir()) # [...,'f1','f2','f3',...]
# Try with list-comprehension
f1_pred = [f1.predict(x) for x in new_data] # NameError: name 'f1' does not exists
# Try with loop
f1_pred = []
for x in new_data:
f1_pred.append(f1.predict(x)) # NameError: name 'f1' does not exists
如果我在函数外部运行这些行,即仅逐行运行(在 VScode 中,交互式窗口中)它工作正常,但是当我运行像 python main.py 这样的函数时,我得到一个 NameError: name 'f1' is not defined 错误。我认为可能exec 没有正确执行,但是print(dir()) 在exec 命令显示之后,变量确实存在。
有人知道为什么吗?
编辑
一个简单的测试
def test():
exec("f= []")
f.append(2)
print(f)
if __name__=="__main__":
test()
> python test.py
> "NameError: name "f" is not defined
也失败了
【问题讨论】:
-
你为什么要使用
exec呢?更好的做法是拥有inputs = {},然后是input[m] = pickle.load(file);动态生成的变量会破坏静态分析工具,通常是代码异味。 -
如果你这样做,你可以使用
input["f1"].predict(x) -
请注意,如果您有任意数量的模型,为什么您只想引用
f1有点不清楚。做类似for model in input.values(): pred = [model.predict(x) for x in new_data]这样的事情不是更有意义吗? -
exec(f"f2=[]") f2.append(5) print(f2) 有效。你能提供一个更完整的例子吗?
-
@CharlesDuffy 因为模型在脚本中被进一步使用(并且这些模型在
model_list中通过它们的名称引用,例如pred_f1 = f1.predict())。
标签: python