3

私はcmd、ユーザーが基本的なURLクエリ文字列形式でテキストコマンドとそれに続くパラメーターを入力できるようにするモジュールを使用して、簡単なPythonスクリプトに取り組んでいます。プロンプトは次のようなもので答えられます

commandname foo=bar&baz=brack

linecmdを使用すると、引数がすべてのメソッドに渡される方法に影響を与えるためにオーバーライドするメソッドを見つけることができないようですdo_*。これらの値で実行したいのですがurlparse.parse_qs、すべてのメソッドでこれをオンラインで呼び出すのdo_*は不器用なようです。

precmdメソッドは、が分割されて解釈される前に行全体を取得するためcommandname、これは私の目的では機能しません。また、このようなクラス内にデコレータを配置する方法についてはあまり詳しくなく、スコープを壊さずにデコレータを実行することもできませんでした。

基本的に、 cmdのPythonドキュメントには次のように書かれています

プロンプトを繰り返し発行し、入力を受け入れ、受信した入力から初期プレフィックスを解析し、アクションメソッドにディスパッチして、行の残りの部分を引数として渡します。

lineその「剰余」に追加の処理を行い、辞書を生成した辞書をすべての関数で解釈するのではなく、引数としてメンバー関数に渡すメソッドを作成したいと思います。

ありがとう!

4

1 に答える 1

3

onecmd()次の簡単な例に示すように、メソッドをオーバーライドできる可能性があります。このonecmd()メソッドは基本的に元のメソッドのコピーですが、引数を関数に渡す前にcmd.pyへの呼び出しを追加します。urlparse.parse_qs()

import cmd
import urlparse

class myCmd(cmd.Cmd):
    def onecmd(self, line):
        """Mostly ripped from Python's cmd.py"""
        cmd, arg, line = self.parseline(line)
        arg = urlparse.parse_qs(arg) # <- added line
        if not line:
            return self.emptyline()
        if cmd is None:
            return self.default(line)
        self.lastcmd = line
        if cmd == '':
            return self.default(line)
        else:
            try:
                func = getattr(self, 'do_' + cmd)
            except AttributeError:
                return self.default(line)
            return func(arg)

    def do_foo(self, arg)
        print arg

my_cmd = myCmd()
my_cmd.cmdloop()

サンプル出力:

(Cmd) foo
{}
(Cmd) foo a b c
{}
(Cmd) foo a=b&c=d
{'a': ['b'], 'c': ['d']}

これはあなたが達成しようとしていることですか?

cmd.Cmdクラスデコレータを使用してサブクラスを変更し、基本的do_* にそのクラスのすべてのメソッドにデコレータ関数を適用する別の潜在的なソリューションを次に示し ます。

import cmd
import urlparse
import types

# function decorator to add parse_qs to individual functions
def parse_qs_f(f):
    def f2(self, arg):
        return f(self, urlparse.parse_qs(arg))
    return f2

# class decorator to iterate over all attributes of a class and apply
# the parse_qs_f decorator to all do_* methods
def parse_qs(cls):
    for attr_name in dir(cls):
        attr = getattr(cls, attr_name)
        if attr_name.startswith('do_') and type(attr) == types.MethodType:
            setattr(cls, attr_name, parse_qs_f(attr))
    return cls

@parse_qs
class myCmd(cmd.Cmd):
    def do_foo(self, args):
        print args

my_cmd = myCmd()
my_cmd.cmdloop()

私はすぐにこれをまとめて、意図したとおりに機能しているように見えますが、落とし穴やこのソリューションをどのように改善できるかについての提案を受け入れています。

于 2012-04-19T21:42:32.067 に答える