2

最初に言いたいのは、私はモジュールなどを調べてきましたが、これに合うようにどのように書き直したらよいかわかりません。

プロジェクト: 私が持っているのは、Skype4Py モジュールを使用した Skype ボットです。11 個のコマンドがあり、1 つのスクリプトが少し大きくなっていることに気付きました。

私は、1 つの main.py ファイルをプラグイン フォルダーにリンクする方法を考えようとしています。このフォルダーには、独自の立派な Python ファイルにすべてのボット関数が含まれています。関数がどのように呼び出されるかを除いて、それはすべて単純に聞こえます。

これは私の 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

別のファイルから関数を実行するようにするには?

4

1 に答える 1

2

このサイズのプログラムの場合、コマンド関数を別々のファイルに入れる必要はありませんが、それ良い編成だと思います。また、何千行ものコードを含むプログラムを作成する場合の良い習慣です。:)

これを行う 1 つの方法は、コマンド メソッドを使用せずに基本的な SkypeBot クラスを作成し、プラグイン ディレクトリからコマンド メソッドをインポートしてクラスに追加することです。新しい属性を既存のクラスに追加するのは簡単です。新しい属性がプロパティであるかメソッドであるかは関係ありません。それらを追加する構文は同じです。(もう少し作業をすれば、新しい属性をインスタンスに追加することさえ可能です。そのため、複数のインスタンスを作成し、それぞれに個別のコマンド セットを持たせることができます。しかし、SkypeBot クラスを使用するプログラムなので、ここでは必要ないと思います。は通常、単一のインスタンスのみを作成します)。

したがって、質問を 2 つの部分に分けることができます。

  1. メソッドを既存のクラスに追加する方法。
  2. これらのメソッドを他のソース ファイルからインポートする方法。

私が言ったように、1)は簡単です。2)も非常に簡単ですが、これまでに行ったことがないため、少し調査とテストを行う必要がありました。私が行ったことがベストプラクティスであるとは約束できませんが、うまくいきます。:)

私は Skype についてあまり知りませんし、その Skype4Py モジュールも持っていません。あなたが言ったように、上記のコードは完全なプログラムではないので、プラグイン メソッドを追加するプロセスを説明するためにいくつかのかなり単純なコードを書きました。別のファイルから既存のクラスに。

メインプログラムの名前は「plugin_demo.py」です。これは、Python パスのどこかに作成する必要があります (通常、Python プログラムを保存する場所など)。このパスは、PYTHONPATH 環境変数で指定する必要があります。

「plugintest/」の構造は次のとおりです。

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

これらの__init__.pyファイルはimport、ディレクトリに Python パッケージが含まれていることを Python の機構が知らせるために使用されます ( 6.4 を参照)。詳細については、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/plugins/」ディレクトリの内容:

__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]

乗算.py

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

「plugintest/」フォルダーを含むディレクトリに移動するcdと、次のコマンドで実行できるはずです

python plugintest/plugin_demo.py

そして、cd「plugintest/」自体を行う場合

python plugin_demo.py

また、インタープリター (または別の Python プログラム) では、次のことができるはずです。

import plugintest

次にmain()、「plugin_demo.py」の関数を実行します

plugintest.plugin_demo.main()

etcの他の通常のバリエーションfrom ... import ...も期待どおりに動作するはずです。

Testインポートされたメソッドをクラスに追加する魔法を実行する "plugin_demo.py" の関数はadd_plugins(). 実行すると、各メソッド名、そのモジュール、およびその関数が出力されます。これは開発中には便利ですが、プログラムが正常に動作するようになったら、これらの print ステートメントの一部をコメント アウトすることになるでしょう。

ご不明な点がございましたら、お気軽にお問い合わせください。

于 2014-10-29T05:46:32.237 に答える