为了账号安全,请及时绑定邮箱和手机立即绑定

更改类时 Jupyter 自动重新加载失败

更改类时 Jupyter 自动重新加载失败

慕码人2483693 2021-11-16 15:11:10
使用 jupyter lab/notebook 时,大多数情况下,我将这两行放在笔记本的第一个单元格中:%reload_ext autoreload%autoreload 2这些通常允许我修改我导入的脚本并使用它们,而无需重新导入它们或重新启动内核。昨天遇到一个问题:我修改了脚本,在笔记本上执行一个单元格报错。重新启动内核并重做导入修复了它。我调查了这个问题,并试图创建一个最小的例子。假设您有以下工作目录:+-- nb.ipynb+-- scripts|   +-- __init__.py|   +-- script1.py笔记本由三个单元格组成:%reload_ext autoreload%autoreload 2\from scripts.script1 import Foo\a = Foo(42)在本实验开始时,script1 包含以下内容:class Foo():    def __init__(self, x):        self.x = x现在,我们执行笔记本的 3 个单元格,一切正常。然后我们转到 script1.py 并将其代码替换为:class Bar():    def __init__(self, x):        self.x = xclass Foo(Bar):    def __init__(self, x):        super().__init__(x)我们保存文件,返回笔记本,并执行包含的单元格a = Foo(42) 这给出了以下错误:[autoreload of script.script failed: Traceback (most recent call last):  File "/home/user/miniconda3/lib/python3.6/site-packages/IPython/extensions/autoreload.py", line 245, in check    superreload(m, reload, self.old_objects)  File "/home/user/miniconda3/lib/python3.6/site-packages/IPython/extensions/autoreload.py", line 384, in superreload    update_generic(old_obj, new_obj)  File "/home/user/miniconda3/lib/python3.6/site-packages/IPython/extensions/autoreload.py", line 323, in update_generic    update(a, b)  File "/home/user/miniconda3/lib/python3.6/site-packages/IPython/extensions/autoreload.py", line 288, in update_class    if update_generic(old_obj, new_obj): continue  File "/home/user/miniconda3/lib/python3.6/site-packages/IPython/extensions/autoreload.py", line 323, in update_generic    update(a, b)  File "/home/user/miniconda3/lib/python3.6/site-packages/IPython/extensions/autoreload.py", line 266, in update_function    setattr(old, name, getattr(new, name))ValueError: __init__() requires a code object with 0 free vars, not 1]重新启动内核或再次执行导入行可解决此问题。为什么autoreload在这种情况下不起作用?PS:这是在python 3.6中完成的,我最初的问题是在python 3.7中
查看完整描述

2 回答

?
慕侠2389804

TA贡献1719条经验 获得超6个赞

一、关于问题

为什么在这种情况下 autoreload 不起作用?

正如错误日志所述:

setattr(old, name, getattr(new, name))
ValueError: __init__() requires a code object with 0 free vars, not 1

autoreload在这里做什么:

它尝试__init__()用新__init__()函数代码对象替换旧函数(代码更改之前的函数)的代码对象。当我检查__init__()代码更改前后函数的空闲变量时,得到如下结果:

检查代码:

Foo.__init__.__code__.co_freevars

结果:

在代码更改之前:(),没有自由变量。

代码更改后:('__class__',),这里有一个空闲变量。这就是错误发生的原因。它不能用新的目标代码替换旧的目标代码。

2.如何解决问题

在这种情况下,因为autoreload仍然是旧的函数对象,所以我们不能做任何事情,只能重新启动内核。

希望这有帮助。


查看完整回答
反对 回复 2021-11-16
?
POPMUISE

TA贡献1765条经验 获得超5个赞

以下对我有用:

from importlib import 
reload  reload(my_module)

不知道这是否适用于所有情况,但比重新启动内核容易得多。


查看完整回答
反对 回复 2021-11-16
  • 2 回答
  • 0 关注
  • 531 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信