我正在编写一个Python应用程序,它将命令作为参数,例如:
$ python myapp.py command1
Run Code Online (Sandbox Code Playgroud)
我希望应用程序是可扩展的,即能够添加实现新命令的新模块,而无需更改主应用程序源.树看起来像:
myapp/
__init__.py
commands/
__init__.py
command1.py
command2.py
foo.py
bar.py
Run Code Online (Sandbox Code Playgroud)
所以我希望应用程序在运行时找到可用的命令模块并执行适当的命令模块.
Python定义了一个__import__函数,它接受一个模块名称的字符串:
__import __(name,globals = None,locals = None,fromlist =(),level = 0)
该函数导入模块名称,可能使用给定的全局变量和局部变量来确定如何解释包上下文中的名称.fromlist给出了应该从name给出的模块导入的对象或子模块的名称.
所以目前我有类似的东西:
command = sys.argv[1]
try:
command_module = __import__("myapp.commands.%s" % command, fromlist=["myapp.commands"])
except ImportError:
# Display error message
command_module.run()
Run Code Online (Sandbox Code Playgroud)
这很好用,我只是想知道是否可能有更惯用的方法来完成我们正在使用此代码.
请注意,我特别不想使用鸡蛋或扩展点.这不是一个开源项目,我不希望有"插件".重点是简化主应用程序代码,并在每次添加新命令模块时无需修改它.
在python中,如何在编程运行时动态地将模块添加到包中.
我希望能够从外部进程将模块添加到包目录中,并且能够在我的程序中使用这些新模块:
import package
def doSomething(name):
pkg = __import__("package." + name)
mod = getattr(pkg, name)
mod.doSomething()
Run Code Online (Sandbox Code Playgroud)
我该怎么做呢?
如何自动加载保存在不同目录和子目录中的所有模块?
我看到这个答案被使用__import__,但它仍然不是我心目中的自动加载.
我在想类似于PHP自动加载器的东西.甚至更好的像Composer自动加载器.
从我迄今为止收集的研究看起来,自动加载器在Python中并不是一个流行的东西(不能确定,因为我是Python的新手).自动加载Python中不鼓励的东西吗?
我的自动加载代码到目前为止,
import os
import sys
root = os.path.dirname(__file__)
sys.path.append(root + "/modules")
sys.path.append(root + "/modules/User")
sys.path.append(root + "/modules/Article")
# IMPORTS MODULES
module = __import__("HelloWorld")
my_class = getattr(module, "HelloWorld")
# This is our application object. It could have any name,
# except when using mod_wsgi where it must be "application"
def application(environ, start_response):
results = []
helloWorld = my_class()
results.append(helloWorld.sayHello())
output = "<br/>".join(results)
print output
...
Run Code Online (Sandbox Code Playgroud)
你可以看到我仍然需要这些行来加载模块,
sys.path.append(root + "/modules") …Run Code Online (Sandbox Code Playgroud) 假设我有这个准系统结构:
project/
main.py
providers/
__init.py__
acme1.py
acme2.py
acme3.py
acme4.py
acme5.py
acme6.py
Run Code Online (Sandbox Code Playgroud)
假设main.py包含(部分):
if complexcondition():
print providers.acme5.get()
Run Code Online (Sandbox Code Playgroud)
哪里__init__.py是空的并且acme*.py包含(部分):
def get():
value=complexcalculation()
return value
Run Code Online (Sandbox Code Playgroud)
如何更改这些文件?
注意:如果答案是"import acme1","import acme2"等等__init__.py,有没有办法实现这一点而不用手动列出它们?