如何使VSCode自动重新加载外部*.py模块?

37

我正在使用 Visual Studio Code 编写 Python 代码,使用多个文件来存储函数,我会在脚本开头导入这些文件。比如说,我有一个名为 "doStuff.py" 的文件,与我的主脚本在同一个文件夹中,其内容如下:

def doStuff():
    print('I am doing stuff!')
    # print('lots of stuff.')

然后我可以通过编写代码“main.py”来导入它,例如:

from doStuff import doStuff
doStuff()

如果我现在运行脚本,然后取消注释doStuff.py函数的第二行,我期望看到doStuff()方法的新行为。不幸的是,这并没有发生。我最近从Spyder切换到VSCode,在Spyder中,这总是自动工作的,但似乎VSCode不会自动重新加载导入的模块。
关于我的当前工作流程的一些信息: 要打开编程环境,我使用“文件/打开文件夹”并选择其中包含main.py和doStuff.py的文件夹。 然后我使用“在Python交互窗口中运行当前文件”来启动我的脚本。 我猜有更好的方法,这可能与launch.json文件有关,但到目前为止,我发现使其使用更改的外部符号的唯一方法是重新启动VSCode。
编辑: 这里的问题:Visual Studio Code:自动刷新文件更改不同,如果我理解正确,因为它涉及重新加载在VS-Code中外部更改的文件。我的问题是关于在交互窗口中重新加载python模块。
编辑2: Screenshot, so you believe me.

1
可能是Visual Studio Code:自动刷新文件更改的重复问题。 - Peter Wood
1
@PeterWood,您发表的问题是否涉及VSCode之外的文件更改?我正在VSCode内更改文件,但它们仍未重新加载。 - Richard
你必须再次运行该脚本。 - Peter Wood
@PeterWood 显然,是的。但在给定的例子中,这只会打印第一条消息而不是第二条。它的行为就像我没有重新启动VSCode之前更改了doStuff.py一样。 - Richard
2
重新启动Python内核也可以解决问题。虽然这样做仍然不够理想,但比重新启动VSCode要好。 - Richard
4个回答

38

更新: 最终解决方案。 只需将此代码添加到您的代码中即可。

%reload_ext autoreload
%autoreload 2

========================================== 我找不到在VSCode中使Python交互自动刷新的方法,但是我尝试了 importlib.reload(),它起到了一定作用。

========================================== 我找不到在VSCode中使Python交互自动刷新的方法,但是我尝试了importlib.reload(),它在某种程度上有效。

import funcs
import importlib
importlib.reload(funcs)
from funcs import *

funcs 是我的 .py 文件,当文件改变时,上面的代码应该被运行。


1
谢谢,这实际上回答了问题。似乎需要将py文件作为模块导入才能重新加载它。添加代码import myPyFile; import importlib; importlib.reload(myPyFile); from myPyFile import MyClass可以重新加载单个类,就像我在原始问题中想要的那样。对我来说仍然有点繁琐。 - Richard
1
嗨,我找到了终极解决方案!请参见我上面的更新。 - KDLin
非常好,我有一个附加组件可以做到这一点:我们可能会将这些行添加到设置"python.dataScience.runMagicCommands"中。这样我们就不需要在所有脚本中包含这些行了。这正是我一直在寻找的。非常感谢! - Richard
它的工作原理是这样的:"python.dataScience.runMagicCommands": "%reload_ext autoreload\n%autoreload 2" - Richard
4
runMagicCommands已经被弃用,您可以使用以下内容替代: "python.dataScience.runStartupCommands": "%load_ext autoreload\\n%autoreload 2"。该内容意为:“运行魔术命令”已不再推荐使用,建议使用新的代码片段来替代它。请将"python.dataScience.runStartupCommands": "%load_ext autoreload\\n%autoreload 2"复制并粘贴到您的代码中,以实现相同的功能。 - Onno Faber
@OnnoFaber 的评论可行,请使用! - Adam Klein

38

现在可以通过添加以下内容来自动设置自动重新加载:

点击这里查看详细信息
    "jupyter.runStartupCommands": [
        "%load_ext autoreload", "%autoreload 2"
    ]

settings.json


4
根据这篇文章 https://stackoverflow.com/questions/65356299/python-datascience-is-unknown-configuration-setting-in-vs-code,配置已发生更改。"jupyter.runStartupCommands" 是新的设置。 - Oliver
1
我喜欢你发布这个<3。 - Alec Mather
1
尽管我像上面那样添加了“jupyter.runStartupCommands”,但这仍然对我无效。我是否还需要安装某种 VS Code 扩展程序才能让它工作?我在 Windows 上使用 VS Code/jupyterlab,使用 wsl2,除此之外一切都正常! - vantom
@tim.rohrer 我刚刚意识到,对我来说重新加载只能以以下方式进行:'from utils import hello' 可以重新加载函数hello(),但是 'from utils import *' 将无法重新加载hello()。[顺便说一句,我知道不推荐使用 from utils import *,但我只是用它来测试自动重新加载,并惊讶地发现它不起作用]。这并不是什么大问题,因为我本来就不应该使用那种语法 :) - vantom
1
谢谢。我也意识到我的问题部分原因是代码检查器,这个问题我还没有解决。无论如何,感谢你的回复。 - tim.rohrer
显示剩余3条评论

12

我本想对Leo的回答作出评论,但是我的声望不够。在VSCode中,leo的片段向我展示了该设置是未知的。这是对我有效的解决办法:

"jupyter.runStartupCommands": [
    "%load_ext autoreload", "%autoreload 2"
],

2
这实际上与VS Code的Python扩展无关,而是与您正在使用的REPL及其提供的功能有关(我假设它是终端中的REPL,但您没有指定是那个还是交互式窗口)。
不管怎样,我真的觉得Spyder的自动重新加载有点令人担忧,因为它涉及许多与之相关的“坑”情况(作为Python导入实现者,我首先知道重新加载模块只在某些情况下起作用,您上面建议的from doStuff import doStuff调用属于不可靠的类别,可能无法按预期工作,除非使用一些我不想依赖的神奇技巧)。

谢谢您的回答。为了明确:我不是使用REPL控制台,而是基于Jupyter服务器的交互式窗口。 - Richard
1
在Spyder中,我的工作流程基于iPython控制台,我必须说它的行为恰好是我想要在VS Code中拥有的。你如何建议重新导入模块呢?对我来说,在多个.py文件中工作只是一种组织方式,我大多使用自己编写的类,而我会在工作时不断更改它们。是否有一种方法可以在不重启vs Code的情况下重新加载我的外部代码?另外,请问您可以进一步说明为什么您认为Spyder令人担忧吗?对我来说,它似乎是期望的行为。 - Richard
@Richard 对于重新加载,您可以尝试使用importlib.reload()手动执行。至于为什么这令人担忧,这是关于Python中导入和对象引用如何工作的技术细节的长时间讨论。如果您特别需要此功能,请在https://github.com/microsoft/vscode-python上打开一个问题。 - Brett Cannon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接