How would I separate my Python File to multiple plugins?
所以,我想说的第一件事是:我一直在研究模块等等,我只是不知道如何重写它来适应这个。
项目:我有一个使用Skype4py模块的Skype bot。我有大约11个命令,我注意到一个脚本有点大。
我正在考虑如何将一个m a in.py文件链接到一个plugin文件夹,该文件夹包含它自己的可尊敬的python文件中的每个bot函数。这听起来很简单,除了如何调用函数。
这里只是简单介绍一下我的Skype bot,它缺少一些更大的功能。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | import Skype4Py, random class SkypeBot(): def __init__(self): self.skype = Skype4Py.Skype() if self.skype.Client.IsRunning == False: self.skype.Client.Start() self.skype.Attach() self.results = ['Yes', 'No', 'Maybe', 'Never'] def main(self): print ' Skype Bot currently running on user: %s' % self.skype.CurrentUserHandle print" Commands Called: " while True: self.skype.OnMessageStatus = self.RunFunction def RunFunction(self, Message, Status): if Status == 'SENT' or Status == 'RECEIVED': cmd = Message.Body.split(' ')[0] if cmd in self.functions.keys(): self.context = Message self.caller = self.context.FromHandle self.functions[cmd](self) def ping(self): print" %s : Ping" % self.caller self.context.Chat.SendMessage('Pong') def say(self): try: response = self.context.Body.split(' ', 1) if response[1] =="-info": print" %s : say -info" % self.caller self.context.Chat.SendMessage("Resends the message entered. " "Usage: !say Hello. " "Example: Bot: Hello.") else: say = response[1] print" %s : Say [%s]" % (self.caller, say) self.context.Chat.SendMessage(say) except: self.context.Chat.SendMessage("Please use -info to properly use the !say command") def eightball(self): try: question = self.context.Body.split(' ', 1) if question[1] =="-info": print" %s : 8Ball -info" % self.caller self.context.Chat.SendMessage("Responds with an answer. " "Usage: !8ball 'Do I have swag?' " "Example: !8Ball Response: 'Yes'") else: random.shuffle(self.results) answer = self.results[3] print" %s : 8Ball [%s]" % (self.caller, question[1]) self.context.Chat.SendMessage("!8Ball Response: %s" % answer) except: self.context.Chat.SendMessage("Please use -info to properly use the !8ball command") #FUNCTIONS LIST #******************** functions = { "!ping": ping, "!say": say, "!8ball": eightball, } if __name__ =="__main__": snayer = SkypeBot() snayer.main() |
所以基本上,我想知道的是,我该如何改变
1 | self.skype.OnMessageStatus = self.RunFunction |
号
以便它从另一个文件运行函数?
对于这种大小的程序来说,不需要将命令函数放在单独的文件中,但我想这是一个很好的组织。以及编写具有数千行代码的程序时的良好实践。:)
一种方法是在不使用任何命令方法的情况下创建一个基本的skypebot类,然后从插件目录导入命令方法并将它们添加到类中。向现有类中添加新属性非常容易,而且无论新属性是属性还是方法,添加它们的语法都是相同的。(稍微多做一点工作,甚至可以向一个实例添加新的属性,这样您就可以有多个实例,每个实例都有自己的一组命令。但我想这不是必需的,因为使用Skypebot类的程序通常只创建一个实例)。
所以我们可以把你的问题分成两部分:
如我所说,1)很容易。2)也很容易,但我以前从未做过,所以我不得不做一些研究和测试,我不能保证我所做的是最佳实践,但它是有效的。:)
我对Skype不太了解,也没有Skype4py模块,正如您所说,上面的代码不是完整的程序,所以我编写了一些相当简单的代码来说明将插件方法从单独的文件添加到现有类的过程。
主程序名为"plugin_demo.py"。为了保持整洁,它位于自己的目录"pluginst/",您应该在您的Python路径中的某个地方创建这个目录(例如您通常保存Python程序的地方)。必须在pythonpath环境变量中指定此路径。
"pluginst/"具有以下结构:
1 2 3 4 5 6 7 | plugintest/ __init__.py plugin_demo.py plugins/ __init__.py add.py multiply.py |
python的
以下是这些文件的内容。首先,进入"pluginst/"本身的文件:
_初始版本
1 2 | __all__ = ['plugin_demo', 'plugins'] from plugintest import * |
号
插件_demo.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | #! /usr/bin/env python #A simple class that will get methods added later from plugins directory class Test(object): def __init__(self, data): self.data = data def add_plugins(cls): import plugins print"Adding plugin methods to %s class" % cls.__name__ for name in plugins.__all__: print name plug = getattr(plugins, name) print plug method = getattr(plug, name) print method setattr(cls, name, method) print"Done " add_plugins(Test) def main(): #Now test it! t = Test([1, 2, 3]); print t.data t.multiply(10); print t.data t.add(5); print t.data if __name__ == '__main__': main() |
现在"pluginst/plugins/"目录的内容是:
_初始版本
1 2 | __all__ = ['add', 'multiply'] from plugintest.plugins import * |
。
Ad.Py
1 2 3 | #A method for the Test class of plugin_demo.py def add(self, m): self.data = [m + i for i in self.data] |
乘法.py
1 2 3 | #A method for the Test class of plugin_demo.py def multiply(self, m): self.data = [m * i for i in self.data] |
。
如果您将cx1〔2〕添加到包含"pluginst/"文件夹的目录中,您应该能够使用
埃多克斯1〔3〕
如果你把1〔2〕改为"pluginst/"。
埃多克斯1〔5〕
另外,在解释器(或另一个python程序)中,您应该能够
埃多克斯1〔6〕
然后运行插件demo.py的
埃多克斯1〔8〕
其他常见的
"plugin-demo.py"中执行将导入方法添加到
我希望这有帮助,如果你有任何问题,请不要犹豫。