我有以下结构:
app.py
modules
|
-- __init__.py
|
-- update.py
我尝试从modules/update.py
dynamicaly调用函数:
import sys
arguments = sys.argv
module = arguments[1]
command = arguments[2]
moduleObj = __import__('modules.'+module) # returns module object "modules"
submodule = getattr(moduleObj, module) # returns the module object "modules.update"
moduleClass = getattr(submodule, module) # returns the class object "update"
# this works because the class has the same name as the file it contains it.
# if the names are different then you have to change that accordingly
result = getattr(moduleClass, command) # returns the attribute with the name =command
print result()
但我发现错误:
文件" app.py",第12行,in print result()TypeError:必须使用update instance作为第一个参数调用unbound方法test()(没有任何内容)
出了什么问题?请帮帮我!
ps:update.py
代码:
import os
class update:
def repositories(self):
os.system('sudo apt-get update')
def system(self):
os.system('sudo apt-get -y upgrade')
def distributive(self):
os.system('sudo apt-get -y dist-upgrade')
def all(self):
self.repositories()
self.system()
self.distributive()
def test(self):
print 'test complete!'
答案 0 :(得分:0)
我认为你传递的是这样的论点:
python app.py update attribute
所以你的程序解释如下:
getattr(__import__('modules.update.update'),command)()
由于您没有具有该名称的模块,因此导致导入错误。
如果我理解正确,您有以下文件结构:
app.py
modules
|
-- __init__.py
|
-- update.py
修改强>
让我假设为了解释,你的update.py
包含:
class update(object):
name = 'update_name'
现在位于app.py
:
import sys
arguments = sys.argv
module = arguments[1]
command = arguments[2]
moduleObj = __import__(module) # returns module object "modules"
submodule = getattr(moduleObj, module) # returns the module object "modules.update"
moduleClass = getattr(submodule, module) # returns the class object "update"
# this works because the class has the same name as the file it contains it.
# if the names are different then you have to change that accordingly
name_attr = getattr(moduleClass, command) # returns the attribute with the name =command
看看你添加了什么印刷品:
print moduleObj
print submodule
print moduleClass
print name_attr
您现在可以通过以下方式调用脚本:
python app.py update name
,输出结果如下:
<module 'modules' from '<path>/modules/__init__.pyc'>
<module 'modules.update' from '<path>/modules/update.pyc'>
<class 'modules.update.update'>
update_name
我认为现在您可以操作代码,但是您希望获得任何您喜欢的对象,甚至可以将它们作为update
和name
之类的参数传递给它们。
修改强>
你不能调用unbounded方法,你需要创建该类的实例,然后调用该实例的方法,这就是错误所说的内容。 所以你需要做类似下面的例子:
import sys
arguments = sys.argv
module = arguments[1]
command = arguments[2]
moduleObj = __import__(module) # returns module "modules"
submodule = getattr(moduleObj, module) # returns the module "modules.update"
localInstance = submodule.update() # create instance of class 'update'
localInstance.test() # call instance method
这将打印:
test complete!
<强> PS:强>
不鼓励对您的方法名称或变量(如system
或all
使用某些字词,更好地更改它们。
希望这会有所帮助。
答案 1 :(得分:0)
关于更新的问题:
更新代码中的错误是由于您需要在调用其方法之前创建类的实例:
result = getattr(moduleClass(), command)
(注意括号)。
我认为错误源于此:
moduleObj = __import__('modules.'+module)
当您在没有fromlist
参数的情况下致电__import__
时,它会返回左模式模块,而不是最右侧模块。为了更清楚,让我举个例子:
In [3]: __import__('xml.dom')
Out[3]: <module 'xml' from '/usr/lib/python2.7/xml/__init__.pyc'>
注意返回xml
模块,不 xml.dom
模块!
即使未返回xml.dom
,也已导入它。您可以通过xml.dom
词典访问sys.modules
:
In [11]: sys.modules['xml.dom']
Out[11]: <module 'xml.dom' from '/usr/lib/python2.7/xml/dom/__init__.pyc'>
要让__import__
返回xml.dom
模块,您需要使用fromlist
参数:
In [4]: __import__('xml.dom', fromlist=[''])
Out[4]: <module 'xml.dom' from '/usr/lib/python2.7/xml/dom/__init__.pyc'>
有关__import__
行为方式can be found here的原因的更多信息。
以下是修复代码的3种不同方法:
使用fromlist
:
moduleObj = __import__('modules.'+module, fromlist=[''])
(分配给fromlist
的内容并不重要,它只需要是一个
非空字符串列表。)
使用sys.modules
:
name = 'modules.'+module
__import__(name)
moduleObj = sys.modules[name]
或者,使用importlib.import_module:
import importlib
moduleObj = importlib.import_module('modules.'+module)
在这三个中,我认为第三个是最具可读性的。