2014-10-28 54 views
2

所以我想说的第一件事:我一直在研究模块等,我只是不安静知道如何重写它以适应此。我如何将我的Python文件分成多个插件?

项目:我有什么是一个Skype机器人使用Skype4Py模块。我有大约11个命令,我注意到一个脚本变得有点大。

我想要考虑如何将一个main.py文件链接到一个插件文件夹,该文件夹包含它自己可敬的Python文件中的每个bot函数。这听起来很简单,除了涉及如何调用函数时。

这只是我的Skype机器人的一个基本的视图,缺少一些较大的功能。

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 "\n\nCommands Called:\n" 

     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. \n" 
               "Usage: !say Hello. \n" 
               "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.\n" 
               "Usage: !8ball 'Do I have swag?'\n" 
               "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() 

所以基本上,我想知道,我怎样才能改变

self.skype.OnMessageStatus = self.RunFunction 

,以便它会从另一个文件中运行的功能呢?

+0

尝试写入文件的名称,然后是类(如果有的话)和模块。 'import Skype4Py',然后通过编写'Skype4Py.a_name()'在'Skype4Py'中调用模块a_name()。让我知道这是否工作或您有任何问题。 – Anthony 2014-10-28 03:00:09

+0

我唯一的问题是我不安静地理解我应该如何听特定的命令来调用,因为从目前我从同一个文件调用它,但如果我混合它,我不知道如何倾听命令的调用。 – user2364549 2014-10-28 03:32:31

+0

它应该是相同的,除了你加上模块名称的前缀。和使用'random'模块一样,除了你创建模块。至于模块本身,你可以用和你在同一个文件中一样的方式编写它。 – Anthony 2014-10-28 19:30:03

回答

2

对于这种规模的项目是不是真的有必要把你的命令的功能为单独的文件,但我想它良好的组织。当你编写一个拥有数千行代码的程序时,这是一个很好的练习。 :)

这样做的一种方法是创建一个基本的SkypeBot类没有任何命令方法,然后从您的插件目录中导入命令方法,并将它们添加到类。向现有类添加新属性非常简单,新属性是属性还是方法并不重要,添加它们的语法是相同的。 (只需要稍微多一点工作,甚至可以为实例添加新的属性,这样您就可以拥有多个实例,每个实例都有自己的一组命令,但我想这不是必须的,因为使用SkypeBot类的程序通常只会创建一个实例)。

因此,我们可以打破你的问题分为两个部分:

  1. 如何方法添加到现有的类。
  2. 如何从其他源文件导入这些方法 。

正如我所说的,1)很容易。 2)也很容易,但我从来没有做过,所以我不得不做一些研究和测试,我不能保证我所做的是最佳实践,但它的工作原理。 :)

我对Skype知之甚少,也没有Skype4Py模块,正如您所说,上面的代码并不是完整的程序,所以我写了一些相当简单的代码来说明将插件方法从单独的文件添加到现有类的过程。

主程序的名称是“plugin_demo.py”。为了保持整洁,它存在于它自己的目录“plugintest /”中,你应该在你的Python路径中创建一个地方(例如,你通常保存你的Python程序的地方)。必须在您的PYTHONPATH环境变量中指定此路径必须

“plugintest /”具有以下结构:

plugintest/ 
    __init__.py 
    plugin_demo.py 
    plugins/ 
     __init__.py 
     add.py 
     multiply.py 

__init__.py文件由Python的import机械用,让它知道,一个目录中包含一个Python包,看到6.4. Packages在Python文档了解更多详情。

这是这些文件的内容。首先,要插入文件 “plugintest /” 本身:

__init__.py

__all__ = ['plugin_demo', 'plugins'] 
from plugintest import * 

plugin_demo.py

#! /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 
    print "Done\n" 

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() 

而现在的“plugintest内容/插件/“目录:

__init__.py

__all__ = ['add', 'multiply'] 
from plugintest.plugins import * 

add.py

#A method for the Test class of plugin_demo.py 
def add(self, m): 
    self.data = [m + i for i in self.data] 

multiply.py

#A method for the Test class of plugin_demo.py 
def multiply(self, m): 
    self.data = [m * i for i in self.data] 

如果cd含有 “plugintest /” 文件夹的目录,你应该能够运行它与

python plugintest/plugin_demo.py

,如果你cd为 “plugintest /” 本身

python plugin_demo.py

而且,在解释(或其他Python程序),你应该能够做到

import plugintest

然后运行main()函数“plugin_demo.py”与

plugintest.plugin_demo.main()

from ... import ...等常见的其它变化也应正常工作。

执行向Test类添加导入方法的魔力的“plugin_demo.py”中的函数是add_plugins()。当它运行时,会打印出每个方法的名称,模块及其功能。这在开发过程中可能非常方便,但是一旦程序运行正常,您可能会注释掉一些打印语句。

我希望这有帮助,如果您有任何问题,请不要犹豫,问。

+0

这是非常有用的,你刚刚澄清了我的问题。我向你们致敬。 – xv70 2016-07-24 15:36:15

相关问题