我已经使用Twisted编写了一个IRC机器人,现在我已经达到了我希望能够动态重新加载功能的程度。
在我的主程序中,我from bots.google import GoogleBot
我已经查看了如何使用reload
重新加载模块,但我仍然无法弄清楚如何动态重新导入类。
因此,给定Python 类,如何动态重新加载类定义?
答案 0 :(得分:2)
重新加载是不可靠的,并且有许多可能失败的极端情况。它适用于重新加载简单,自包含的脚本。如果要在不重新启动的情况下动态重新加载代码,请考虑使用forkloop:
http://opensourcehacker.com/2011/11/08/sauna-reload-the-most-awesomely-named-python-package-ever/
答案 1 :(得分:1)
我明白了,这是我使用的代码:
def reimport_class(self, cls):
"""
Reload and reimport class "cls". Return the new definition of the class.
"""
# Get the fully qualified name of the class.
from twisted.python import reflect
full_path = reflect.qual(cls)
# Naively parse the module name and class name.
# Can be done much better...
match = re.match(r'(.*)\.([^\.]+)', full_path)
module_name = match.group(1)
class_name = match.group(2)
# This is where the good stuff happens.
mod = __import__(module_name, fromlist=[class_name])
reload(mod)
# The (reloaded definition of the) class itself is returned.
return getattr(mod, class_name)
答案 2 :(得分:0)
执行from ... import ...
时,它会将对象绑定到本地名称空间,因此您需要重新导入它。但是,由于模块已经加载,它只会重新导入相同版本的类,因此您还需要重新加载模块。所以这应该这样做:
from bots.google import GoogleBot
...
# do stuff
...
reload(bots.google)
from bots.google import GoogleBot
如果由于某种原因您不知道模块名称,可以从GoogleBot获取。模块。
答案 3 :(得分:0)
更好的是对插件进行子处理,然后在文件更改时重新加载子进程,重新加载插件进程。
编辑:清理干净。
答案 4 :(得分:0)
使用reload(module)
表单时,无法使用from X import Y
重新加载模块。在这种情况下,您必须执行reload(sys.modules['module'])
之类的操作。
这可能不一定是最好的方式来做你想要的,但是它有效!
import bots.google
class BotClass(irc.IRCClient):
def __init__(self):
global plugins
plugins = [bots.google.GoogleBot()]
def privmsg(self, user, channel, msg):
global plugins
parts = msg.split(' ')
trigger = parts[0]
if trigger == '!reload':
reload(bots.google)
plugins = [bots.google.GoogleBot()]
print "Successfully reloaded plugins"
答案 5 :(得分:0)
您可以使用sys.modules
根据用户输入动态重新加载模块。
假设您有一个包含多个插件的文件夹,例如:
module/
cmdtest.py
urltitle.py
...
您可以使用sys.modules
以这种方式根据用户输入加载/重新加载模块:
import sys
if sys.modules['module.' + userinput]:
reload(sys.modules['module.' + userinput])
else:
' Module not loaded. Cannot reload '
try:
module = __import__("module." + userinput)
module = sys.modules["module." + userinput]
except:
' error when trying to load %s ' % userinput
答案 6 :(得分:0)
def reload_class(class_obj):
module_name = class_obj.__module__
module = sys.modules[module_name]
pycfile = module.__file__
modulepath = string.replace(pycfile, ".pyc", ".py")
code=open(modulepath, 'rU').read()
compile(code, module_name, "exec")
module = reload(module)
return getattr(module,class_obj.__name__)
你可以对此做很多错误检查,如果使用全局变量,你可能需要弄清楚会发生什么。