在不修改 sys.path 的情况下在外部目录中查找 类
Finding classes in an external directory without modifying sys.path
我有一个函数,它接受一个包含一些 python 文件的外部路径,并发现这些文件中存在的任何 classes。它 returns class 名称和 class 本身的映射,以便我可以根据需要创建一个对象。下面的代码按照我的预期工作,但我试图在不附加 sys.path.
的情况下执行此操作
def find_plugins(path):
sys.path.append(path)
plugin_map = {}
current_module_name = os.path.splitext(os.path.basename(path))[0]
for file in glob.glob(path + '/*.py'):
name = os.path.splitext(os.path.basename(file))[0]
if name.startswith('__'):
continue
module = importlib.import_module(name, package=current_module_name)
for member in dir(module):
plugin_class = getattr(module, member)
if plugin_class and inspect.isclass(plugin_class):
plugin_map[member] = plugin_class
return plugin_map
如果删除 sys.path 行,我会得到以下堆栈跟踪:
ModuleNotFoundError: No module named 'plugin'
其中 'plugin' 是提供给函数的路径中的 plugin.py
文件。甚至可以在不附加 sys.path 的情况下执行此操作吗?
您可以使用 accepted answer to the question
How to import a module given the full path 中显示的技术来完成,它不需要操作 sys.path
。
import importlib.util
import inspect
from pathlib import Path
def find_plugins(path):
plugins = {}
for module_path in Path(path).glob('*.py'):
module_name = module_path.stem
if not module_name.startswith('__'):
# Load module.
spec = importlib.util.spec_from_file_location(module_name, module_path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module) # Execute module in its own namespace.
# Extract classes defined in module.
for member in dir(module):
plugin_class = getattr(module, member)
if plugin_class and inspect.isclass(plugin_class):
plugins[member] = plugin_class
return plugins
if __name__ == '__main__':
from pprint import pprint
plugins_folder = '/path/to/plugins'
plugins = find_plugins(plugins_folder)
pprint(plugins)
我有一个函数,它接受一个包含一些 python 文件的外部路径,并发现这些文件中存在的任何 classes。它 returns class 名称和 class 本身的映射,以便我可以根据需要创建一个对象。下面的代码按照我的预期工作,但我试图在不附加 sys.path.
的情况下执行此操作def find_plugins(path):
sys.path.append(path)
plugin_map = {}
current_module_name = os.path.splitext(os.path.basename(path))[0]
for file in glob.glob(path + '/*.py'):
name = os.path.splitext(os.path.basename(file))[0]
if name.startswith('__'):
continue
module = importlib.import_module(name, package=current_module_name)
for member in dir(module):
plugin_class = getattr(module, member)
if plugin_class and inspect.isclass(plugin_class):
plugin_map[member] = plugin_class
return plugin_map
如果删除 sys.path 行,我会得到以下堆栈跟踪:
ModuleNotFoundError: No module named 'plugin'
其中 'plugin' 是提供给函数的路径中的 plugin.py
文件。甚至可以在不附加 sys.path 的情况下执行此操作吗?
您可以使用 accepted answer to the question
How to import a module given the full path 中显示的技术来完成,它不需要操作 sys.path
。
import importlib.util
import inspect
from pathlib import Path
def find_plugins(path):
plugins = {}
for module_path in Path(path).glob('*.py'):
module_name = module_path.stem
if not module_name.startswith('__'):
# Load module.
spec = importlib.util.spec_from_file_location(module_name, module_path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module) # Execute module in its own namespace.
# Extract classes defined in module.
for member in dir(module):
plugin_class = getattr(module, member)
if plugin_class and inspect.isclass(plugin_class):
plugins[member] = plugin_class
return plugins
if __name__ == '__main__':
from pprint import pprint
plugins_folder = '/path/to/plugins'
plugins = find_plugins(plugins_folder)
pprint(plugins)