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

使用 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 = x


class 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中


慕码人2483693
浏览 532回答 2
2回答

慕侠2389804

一、关于问题为什么在这种情况下 autoreload 不起作用?正如错误日志所述:setattr(old, name, getattr(new, name)) ValueError: __init__() requires a code object with 0 free vars, not 1autoreload在这里做什么:它尝试__init__()用新__init__()函数代码对象替换旧函数(代码更改之前的函数)的代码对象。当我检查__init__()代码更改前后函数的空闲变量时,得到如下结果:检查代码:Foo.__init__.__code__.co_freevars结果:在代码更改之前:(),没有自由变量。代码更改后:('__class__',),这里有一个空闲变量。这就是错误发生的原因。它不能用新的目标代码替换旧的目标代码。2.如何解决问题在这种情况下,因为autoreload仍然是旧的函数对象,所以我们不能做任何事情,只能重新启动内核。希望这有帮助。

POPMUISE

以下对我有用:from importlib import  reload  reload(my_module)不知道这是否适用于所有情况,但比重新启动内核容易得多。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python