This is an example of monitoring a specific directory and importing / reloading when a Python module is created / updated.
File monitoring can be implemented by yourself, but it's easy to do with existing libraries.
Here we use a module called watchdog. You can use watchdog to detect events such as creating / updating / deleting files in a specific directory.
You usually use the import statement to import a module, but you cannot specify the module name as a string.
If you want to dynamically specify the module you want to import with a character string, use the standard module impotlib.import_module (). To do.
Module name cannot be specified as a character string in the import statement
>>> import 'sys'
  File "<stdin>", line 1
    import 'sys'
               ^
SyntaxError: invalid syntax
importlib.import_module()Then specify the module name as a character string
>>> import importlib
>>> importlib.import_module('sys')
>>> sys = importlib.import_module('sys')
>>> sys
<module 'sys' (built-in)>
Updating the Python file of an imported module will not be reflected in the running program. Even if you execute the import statement or ʻimpotlib.import_module ()` again, it will not be reflected.
Use importlib.reload () to reload the imported module.
python
>>> with open('a.py', 'w') as f:
...     f.write('def f():\n    print("1")')
...
23
>>> import a
>>> a.f()
1
>>> with open('a.py', 'w') as f:
...     f.write('def f():\n    print("2")')
...
23
>>> a.f()
1
>>> import a
>>> a.f()
1
>>> import importlib
>>> a = importlib.import_module('a')
>>> a.f()
1
>>> a = importlib.reload(a)
>>> a.f()
2
Works with Python 3.4 and above.
plugin_manager.py
import sys
import time
from importlib import import_module, reload
from pathlib import Path
from watchdog.events import FileSystemEvent, PatternMatchingEventHandler
from watchdog.observers import Observer
class PluginManager:
    class Handler(PatternMatchingEventHandler):
        def __init__(self, manager: 'PluginManager', *args, **kwargs):
            super().__init__(*args, **kwargs)
            self.manager = manager
        def on_created(self, event: FileSystemEvent):
            print(event)
            if event.src_path.endswith('.py'):
                self.manager.load_plugin(Path(event.src_path))
        def on_modified(self, event):
            print(event)
    def __init__(self, path: str):
        self.plugins = {}
        self.path = path
        self.observer = Observer()
        sys.path.append(self.path)
    def start(self):
        self.scan_plugin()
        self.observer.schedule(self.Handler(self, patterns='*.py'), self.path)
        self.observer.start()
    def stop(self):
        self.observer.stop()
        self.observer.join()
    def scan_plugin(self):
        for file_path in Path(self.path).glob('*.py'):
            self.load_plugin(file_path)
    def load_plugin(self, file_path):
        module_name = file_path.stem
        if module_name not in self.plugins:
            self.plugins[module_name] = import_module(module_name)
            print('{} loaded.'.format(module_name))
        else:
            self.plugins[module_name] = reload(self.plugins[module_name])
            print('{} reloaded.'.format(module_name))
def main():
    plugin_manager = PluginManager('plugins/')
    plugin_manager.start()
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        plugin_manager.stop()
if __name__ == '__main__':
    main()
plugins/To a.Start with py
a loaded.
plugins/To b.Create py
<FileCreatedEvent: src_path='plugins/b.py'>
b loaded.
<DirModifiedEvent: src_path='plugins/'>
<DirModifiedEvent: src_path='plugins/__pycache__'>
b.To pyprint('bbb')Write and save
<FileCreatedEvent: src_path='plugins/b.py'>
bbb
b reloaded.
<DirModifiedEvent: src_path='plugins/'>
<DirModifiedEvent: src_path='plugins/__pycache__'>
--I think the watchdog handler should call ʻon_modified () when it detects a file update, but ʻon_created () was called.
Recommended Posts