Python: Reload source files
When I was writing BUTT - an irc bot, I wanted to create a mini plugin system, to add or modify code without restarting any process. Python allows this natively using the imp module. In the following examples, I’ll show how to use the load_source procedure to load and parse a new source file.
Here a very simple module we’ll import during execution time:
#!/usr/bin/env python
class TestModule:
def __init__(self):
pass
def myfunction(self):
print "Calling myfunction"
Let’s load module:
#!/usr/bin/env python
import os, shutil
import imp
def load_module(module_name):
print "Loading module %s" % module_name
modfile = os.path.join(os.getcwd(), module_name + '.py')
module = imp.load_source(module_name, modfile)
print module
# Returns <module 'test' from '/home/mycroft/imp/test.pyc'>
print dir(module)
# Permet de lister les differents attributs de l'objet importé.
# Returns ['TestModule', '__builtins__', '__doc__', '__file__', '__name__', '__package__']
for objname in dir(module):
# Je veux specifiquement les modules suffixés "Module":
if objname.endswith('Module'):
modclass = getattr(module, objname)
print modclass
# Returns test.TestModule
print dir(modlass)
# Returns ['__doc__', '__init__', '__module__', 'myfunction']
return modclass
return None
Just testing the whole thing, with reloading a module:
if __name__ == '__main__':
modclass = load_module('test')
instance = modclass()
instance.myfunction()
# We move away test.py, and copy test_new.py to test.py.
print
shutil.move('test.py', 'test_old.py')
shutil.move('test_new.py', 'test.py')
modclass = load_module('test')
instance = modclass()
instance.myfunction()
shutil.move('test.py', 'test_new.py')
shutil.move('test_old.py', 'test.py')
And we’ll get:
$ ./modules.py
Loading module test
<module 'test' from '/home/mycroft/imp/test.py'>
['TestModule', '__builtins__', '__doc__', '__file__', '__name__', '__package__']
test.TestModule
['__doc__', '__init__', '__module__', 'myfunction']
Calling myfunction
Loading module test
<module 'test' from '/home/mycroft/imp/test.py'>
['TestModule', '__builtins__', '__doc__', '__file__', '__name__', '__package__']
test.TestModule
['__doc__', '__init__', '__module__', 'myfunction']
Calling (new) myfunction