2014-10-28 48 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

相關問題