2

システム管理者として、私はサブプロセスを介してコマンドを呼び出すスクリプトを何度も書いています。コマンドを実際に実行したくない場合があり、何が実行されるかを確認したいだけです。したがって、私のコードは次のような行でいっぱいでした:

alaroffcmd = 'someBinary -h %s' %someHostName
...
if options.tstmd:       
   print alaroffcmd
else:
   chctxt = sp.Popen(alamoffcmd,shell=True, stdout=sp.PIPE) 
   ...

私は「テストモード」が非常に役立つだろうと思っていました。

使用例として:

lsp=nPopen('ls -l',shell=True, stdout=sp.PIPE, testmode=True)

発行するコマンドを出力するだけです。これは冗長に思えるかもしれませんが、実際には、スクリプトで決定された条件に基づいて決定される非常に複雑なコマンドを使用してサブプロセスを呼び出すことがあります(上記の例はsomeHostName

これを、 initメソッドをオーバーライドして関数を拡張する方法の例として使用しました。subprocess.Popenこれが私のニーズに合うように拡張した方法です:

import subprocess as sp

class nPopen(sp.Popen):
    def __init__(self, args, bufsize=0, executable=None,
                 stdin=None, stdout=None, stderr=None,
                 preexec_fn=None, close_fds=False, shell=False,
                 cwd=None, env=None, universal_newlines=False,
                 startupinfo=None, creationflags=0,testmode=False):

        if testmode: 
            print args
            return None

     p = sp.Popen.__init__(self,args, bufsize, executable,
                 stdin, stdout, stderr,
                 preexec_fn, close_fds, shell,
                 cwd, env, universal_newlines,
                 startupinfo, creationflags)

        return p

これは期待どおりに機能しますが、__init__メソッドをオーバーライドしてクラスを拡張したことがないので、これが正しいかどうか疑問に思っていました。つまり、これを行うためのよりPython的な方法はありますか?superPython3との互換性を高めるために使用する必要がありますか?

4

1 に答える 1

4

Popenオブジェクトの機能を変更したくないように思われるので、サブクラスはまったく使用しません。コンストラクターの機能を変更したいだけのようです。

Popen引数を出力するだけのダミークラスを作成します。(これはPython 3.xスタイルを使用して記述されていますが、Python 2.xに変換するのは簡単です。)

class DummyPopen(object):
    def __init__(self, *args, **kw):
        print('Popen({})'.format(
            ', '.join([repr(arg) for arg in args] +
                      ['{}={!r}'.format(*pair) for pair in kw.items()])))
        self.returncode = 1

    def wait(self):
        return 1

    # et cetera

その後、必要に応じてダミークラスの使用をトリガーできます。

def Popen(*args, testmode=False, **kw):
    if testmode:
        return DummyPopen(*args, **kw)
    return subprocess.Popen(*args, **kw)

あるいは:

if testmode:
    Popen = DummyPopen
else:
    Popen = subprocess.Popen

これは、Pythonの「ダックタイピング」規則を利用します。オブジェクトと同じインターフェイスを持つオブジェクトは、乱用しすぎない限り、Popen機能的にオブジェクトと区別できません。Popenisinstance()

これらの方法の両方Popenで、モジュールからインポートできることに注意してください。

from mymodule import Popen
于 2012-11-14T17:00:42.730 に答える