I have a long-running Python server and would like to be able to upgrade a service without restarting the server. What\'s the best way do do this?
if foo.py
Removing modules from sys.modules requires 'None' types to be deleted as well.
Method 1:
import sys
import json ## your module
for mod in [ m for m in sys.modules if m.lstrip('_').startswith('json') or sys.modules[m] == None ]: del sys.modules[mod]
print( json.dumps( [1] ) ) ## test if functionality has been removed
Method 2, using bookkeeping entries, to remove all dependencies:
import sys
before_import = [mod for mod in sys.modules]
import json ## your module
after_import = [mod for mod in sys.modules if mod not in before_import]
for mod in [m for m in sys.modules if m in after_import or sys.modules[m] == None]: del sys.modules[mod]
print( json.dumps( [2] ) ) ## test if functionality has been removed
Optional, just to be certain all entries are out, if you so choose:
import gc
gc.collect()
Enthought Traits has a module that works fairly well for this. https://traits.readthedocs.org/en/4.3.0/_modules/traits/util/refresh.html
It will reload any module that has been changed, and update other modules and instanced objects that are using it. It does not work most of the time with __very_private__
methods, and can choke on class inheritance, but it saves me crazy amounts of time from having to restart the host application when writing PyQt guis, or stuff that runs inside programs such as Maya or Nuke. It doesn't work maybe 20-30 % of the time, but it's still incredibly helpful.
Enthought's package doesn't reload files the moment they change - you have to call it explicitely - but that shouldn't be all that hard to implement if you really need it
For those like me who want to unload all modules (when running in the Python interpreter under Emacs):
for mod in sys.modules.values():
reload(mod)
More information is in Reloading Python modules.
Those who are using python 3 and reload from importlib.
If you have problems like it seems that module doesn't reload... That is because it needs some time to recompile pyc (up to 60 sec).I writing this hint just that you know if you have experienced this kind of problem.
Another way could be to import the module in a function. This way when the function completes the module gets garbage collected.
I got a lot of trouble trying to reload something inside Sublime Text, but finally I could wrote this utility to reload modules on Sublime Text based on the code sublime_plugin.py
uses to reload modules.
This below accepts you to reload modules from paths with spaces on their names, then later after reloading you can just import as you usually do.
def reload_module(full_module_name):
"""
Assuming the folder `full_module_name` is a folder inside some
folder on the python sys.path, for example, sys.path as `C:/`, and
you are inside the folder `C:/Path With Spaces` on the file
`C:/Path With Spaces/main.py` and want to re-import some files on
the folder `C:/Path With Spaces/tests`
@param full_module_name the relative full path to the module file
you want to reload from a folder on the
python `sys.path`
"""
import imp
import sys
import importlib
if full_module_name in sys.modules:
module_object = sys.modules[full_module_name]
module_object = imp.reload( module_object )
else:
importlib.import_module( full_module_name )
def run_tests():
print( "\n\n" )
reload_module( "Path With Spaces.tests.semantic_linefeed_unit_tests" )
reload_module( "Path With Spaces.tests.semantic_linefeed_manual_tests" )
from .tests import semantic_linefeed_unit_tests
from .tests import semantic_linefeed_manual_tests
semantic_linefeed_unit_tests.run_unit_tests()
semantic_linefeed_manual_tests.run_manual_tests()
if __name__ == "__main__":
run_tests()
If you run for the first time, this should load the module, but if later you can again the method/function run_tests()
it will reload the tests files. With Sublime Text (Python 3.3.6
) this happens a lot because its interpreter never closes (unless you restart Sublime Text, i.e., the Python3.3
interpreter).