[英]How do I run global code without calling the file
I'm writing a python application that allows users to write their own plugins and extend the core functionality I provide - 我正在编写一个python应用程序,允许用户编写自己的插件并扩展我提供的核心功能 -
$ tree project_dir/
.
├── application.py
├── plugins
│ ├── __init__.py
│ ├── example_plugin.py
│ ├── plugin1.py
│ ├── plugin2.py
│ └── plugin3
│ ├── sounds
│ │ └── test.wav
│ └── player.py
└── plugins_manager.py
plugins_manager.py - plugins_manager.py -
class Manager(object):
def __init__(self):
self.plugins = {}
def register_plugin(self, name, plugin_func):
self.plugins[name] = plugin_func
application.py initializes Manager
instance globally - application.py全局初始化
Manager
实例 -
manager = Manager()
def main():
print manager.plugins
main()
Each plugin is required to import the Manager
instance from application.py
and register itself like, plugin1.py - 每个插件都需要从
application.py
导入Manager
实例并注册自己,如plugin1.py -
from application import manager
PLUGIN_NAME = "AAC_Player"
def plugin_function(options):
# do something
manager.register_plugin(PLUGIN_NAME, plugin_function)
Now when I run application.py, obviously nothing gets printed. 现在,当我运行application.py时,显然没有任何内容被打印出来。 How do I make the plugins register themselves (call
.register_plugin()
) at program startup? 如何在程序启动时自己注册插件(调用
.register_plugin()
)?
So on that lines, a more generalised question would be - How can I make python execute a line of code that's global in a file without actually running the file? 所以在这一行上,一个更普遍的问题是 - 如何让python执行一行代码,这些代码在文件中是全局的而不实际运行文件?
Suggestions on improving the plugin architecture welcome! 关于改进插件架构的建议欢迎!
You can use the __import__()
builtin to import the plugins, and then include the register_plugin()
call in either the plugin file example_plugin.py
or in __init__.py
if it's a directory. 您可以使用
__import__()
内置来导入插件,然后在插件文件example_plugin.py
或__init__.py
. __import__()
如果它是目录register_plugin()
包含register_plugin()
调用。
For example, let's say this is your project structure: 例如,假设这是您的项目结构:
./
application.py
plugins_manager.py
plugins/
__init__.py
plugin1.py
plugin2.py
plugin3/
__init__.py
Plugins have these contents: 插件包含以下内容:
$ cat plugins/plugin1.py
print 'Plugin 1'
$ cat plugins/plugin2.py
print 'Plugin 2'
$ cat plugins/plugin3/__init__.py
print 'Plugin 3'
In plugins_manager.py
, identify the plugins and import them in: 在
plugins_manager.py
,标识插件并将其导入:
from os import listdir
from os.path import exists, isdir, basename, join, splitext
def is_plugin(filename):
filepath = join('plugins', filename)
_, ext = splitext(filepath)
# Ignore plugins/__init__.py
if filename == '__init__.py':
return False
# Find single file plugins
if ext == '.py':
return True
# Find plugins packaged in directories
if isdir(filepath) and exists(join(filepath, '__init__.py')):
return True
return False
plugin_names = [ splitext(p)[0] for p in listdir('plugins/') if is_plugin(p) ]
plugins = [ __import__('plugins.' + p) for p in plugin_names ]
Should get output similar to: 应该得到类似于的输出:
Plugin 1
Plugin 2
Plugin 3
Note that in this case the plugins
variable contains a list of the module objects imported. 请注意,在这种情况下,
plugins
变量包含导入的模块对象的列表。
Strictly speaking I'd say there is no way to run code without it being invoked somehow. 严格来说,我会说如果不以某种方式调用代码就无法运行代码。 To do this, the running program can use
为此,正在运行的程序可以使用
import importlib
so that once you've found the file you can import it with: 这样,一旦找到该文件,您可以将其导入:
mod = importlib.import_module(import_name, pkg_name)
and if that file provides a known function (Run in this case) you can call it with: 如果该文件提供已知函数(在这种情况下运行),您可以使用以下命令调用它:
mod.Run(your_args)
This works for Python 2.7. 这适用于Python 2.7。 Version 3 might be different.
版本3可能不同。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.