33

I am working on python code in Visual Studio Code and use several files for functions, which I import at the beginning of a script. Let's say for example I have a file "doStuff.py" in the same folder as my main script with the content

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

which I would then import in another script, e.g. "main.py" by writing

from doStuff import doStuff
doStuff()

If I now run the script and afterwards e.g. uncomment the second line of the function in doStuff.py, I would expect to see the new behavior of my doStuff() method. Unfortunately this doesn't happen. I recently switched from Spyder to VSCode and in Spyder this always used to work automatically, but it seems VSCode does not auto-reload the imported modules.

Some info about my current workflow: To open the programming environment, I use "File/Open Folder" and select the folder in which main.py and doStuff.py are located. I am then using "Run Current File in Python Interactive Window" to start my scripts. I am guessing there are better ways and it might have something to do with the launch.json file, but so far the only way I have found to make it use the changed external symbol is restarting VSCode.

Edit: The issue here: Visual Studio Code: Auto-refresh file changes is different, if I understand it correctly, since it is about externally changed files to be reload in VS-Code. My issue is concerned with python modules being reloaded in the interactive window.

Edit 2: Screenshot, so you believe me.

Richard
  • 709
  • 1
  • 6
  • 15
  • 1
    Possible duplicate of [Visual Studio Code: Auto-refresh file changes](https://stackoverflow.com/questions/30078077/visual-studio-code-auto-refresh-file-changes) – Peter Wood May 09 '19 at 12:41
  • 1
    @PeterWood The issue you posted was concerned with filechanges outside of VSCode wasn't it? I am changing the files within VSCode but they are still not being reloaded. – Richard May 09 '19 at 12:59
  • You have to run the script again. – Peter Wood May 09 '19 at 15:31
  • @PeterWood well obviously, yes. But in the given example. this would only print the first message and not the second one. It behaves as if I had not changed doStuff.py until I restart VSCode. – Richard May 10 '19 at 09:40
  • 2
    Restarting the Python Kernel also works. It's still not satisfying having to do so, but better than restarting VSCode. – Richard May 23 '19 at 14:05

4 Answers4

35

Update: The ultimate solution. Just add this in you code.

%reload_ext autoreload
%autoreload 2

========================================== I could not find the way make python interactive of vscode auto re-fresh when the .py file changes. but I try importlib.reload(), it works some way.

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

funcs is my .py files, and code above should be run when the file changes.

KDLin
  • 404
  • 4
  • 5
  • 1
    Thank you, this actually answers the question. It seems to be necessary to import the py file as a module to be able to reload it. Adding the code `import myPyFile; import importlib; importlib.reload(myPyFile); from myPyFile import MyClass` makes it possible to reload a single class, as I wanted to in the orignal question. Still seems a bit tedious to me.. – Richard Jul 29 '19 at 14:29
  • 1
    hi, I found the ultimate solution! Seeing my update above. – KDLin Sep 06 '19 at 06:14
  • Very nice, I have an add-on for that: We can probably add these lines into the setting `"python.dataScience.runMagicCommands"`. That way we don't need to include those lines into all the scripts. That is exactly what I had been looking for. Thank you very much! – Richard Sep 09 '19 at 11:31
  • It works like this: "python.dataScience.runMagicCommands": "%reload_ext autoreload\n%autoreload 2" – Richard Sep 10 '19 at 07:48
  • 4
    `runMagicCommands` is deprecated. You can use: `"python.dataScience.runStartupCommands": "%load_ext autoreload\\n%autoreload 2"` – Onno Faber Apr 27 '20 at 23:54
  • @OnnoFaber comment works, use that! – Adam Klein Aug 31 '22 at 19:29
32

It is now possible to set up autoreload automatically by adding:

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

to settings.json.

Oliver
  • 150
  • 5
Leo
  • 2,775
  • 27
  • 29
  • 4
    the config has changed according to this https://stackoverflow.com/questions/65356299/python-datascience-is-unknown-configuration-setting-in-vs-code `"jupyter.runStartupCommands"` is the new one – Oliver Mar 27 '21 at 02:56
  • 1
    i love you for posting this <3 – Alec Mather May 26 '22 at 21:58
  • 1
    This still isn't working for me even though I added the 'jupyter.runStartupCommands' as above. Do I also have to install some kind of VS Code extension to get it to work? I using VS Code/jupyterlab on Windows with wsl2 and everything else works well except this! – vantom Jan 27 '23 at 09:24
  • @vantom, I just came back to this question because I too am not seeing this work. If you get it solved, please report back. I'll do the same. – tim.rohrer Jan 27 '23 at 12:50
  • FWIW I just tried on 1.74.3 (2023 Jan) and: 1. it still works for me; 2. if I remove it the modules are no longer autoreloaded. – Leo Jan 27 '23 at 13:31
  • @tim.rohrer I just realized that for me the reloading does work but only in the following way: 'from utils import hello' will work to reload a function hello() but 'from utils import *' will not reload hello(). [Side note, I know it's not recommended to use from utils import *, but I was just using it to test the autoreload and I was surprised to find that it doesn't work]. Not a big deal since I shouldn't be using that syntax anyway:) – vantom Feb 01 '23 at 15:35
  • 1
    Thank you. I have also realized that part of my problem was simply the linter, which I've not solved yet. Anyway, I appreciate you coming back. – tim.rohrer Feb 01 '23 at 15:57
  • best solution because it is vscode specific (not adding the lines before import in .py-scripts) – Johan May 16 '23 at 09:01
10

I would have commented on leo's answer, but I don't have enough reputation. The leo's snippet in VSCode showed me that the setting is unknown. This is what worked for me:

"jupyter.runStartupCommands": [
    "%load_ext autoreload", "%autoreload 2"
],
koral
  • 525
  • 7
  • 23
2

This actually isn't about the Python extension for VS Code but the REPL you're using and what it provides (which I assume is the REPL in the terminal, but you didn't specify if it was that or the interactive window).

Regardless, I honestly find it a bit worrisome that Spyder would do auto-reloading as it has so many "gotcha" situations related to it (as the implementer of import in Python I know first-hand that reloading a module only works in select cases and the one you are suggesting above falls within the category of not getting what you expect due to your from doStuff import doStuff call in a reliable fashion without some magical hacks that I wouldn't want to rely upon working).

Brett Cannon
  • 14,438
  • 3
  • 45
  • 40
  • thank you for your answer. To specify: I am not using the REPL console, but the interactive window that is based on a Jupyter server. – Richard May 19 '19 at 13:22
  • 1
    In Spyder, my workflow is based on an iPython console and I have to say that its behavior is exactly what I would like to have in VS Code. How would you recommend re-importing the module then? For me, working in multiple .py files is just a matter of organization and I mostly use self written classes which I continuously change while working. Is there a way to reload my external code without restarting vs Code? Also, could you please further specify why do you think of Spyder as worrisome? To me it seems that would be the desired behavior. – Richard May 19 '19 at 13:28
  • @Richard For reloading you can try it manually with `importlib.reload()`. As for why it's worrisome, it's a long discussion about technical aspects of how imports and object references work in Python. And if you specifically want this feature then please open an issue at https://github.com/microsoft/vscode-python . – Brett Cannon May 24 '19 at 22:19