1

bash(シェル)をPythonに統合することを発見sh moduleした後、ほとんどの場合、短いシェルスクリプトの代わりにそれを使用しています(shは基本的にステロイドのサブプロセスであり、このタイプの統合により、非常に「pythonic bashスクリプト」を使用できます)。確かに、私は次のようなことができます

from sh import ifconfig
print(ifconfig("wlan0"))

現在ifconfigは sh モジュールの一部ではありません。どうやら、この関数は動的に構築されます。今、私はこれがどのように正確に行われているのか非常に興味があります.

それで、私の質問はそれがどのように機能するのですか?

__enter__()最初は、そのような慣行を一種の「プロトコル」( orに似たもの) として説明する PEP があると思いましたnext()。しかし、これを説明する PEP は見つかりませんでした。

4

1 に答える 1

0

shソースコードから:

# this is a thin wrapper around THIS module (we patch sys.modules[__name__]).
# this is in the case that the user does a "from sh import whatever"
# in other words, they only want to import certain programs, not the whole
# system PATH worth of commands.  in this case, we just proxy the
# import lookup to our Environment class
class SelfWrapper(ModuleType):
    def __init__(self, self_module, baked_args={}):
        # this is super ugly to have to copy attributes like this,
        # but it seems to be the only way to make reload() behave
        # nicely.  if i make these attributes dynamic lookups in
        # __getattr__, reload sometimes chokes in weird ways...
        for attr in ["__builtins__", "__doc__", "__name__", "__package__"]:
            setattr(self, attr, getattr(self_module, attr, None))

        # python 3.2 (2.7 and 3.3 work fine) breaks on osx (not ubuntu)
        # if we set this to None.  and 3.3 needs a value for __path__
        self.__path__ = []
        self.self_module = self_module
        self.env = Environment(globals(), baked_args)

    def __setattr__(self, name, value):
        if hasattr(self, "env"): self.env[name] = value
        ModuleType.__setattr__(self, name, value)

    def __getattr__(self, name):
        if name == "env": raise AttributeError
        return self.env[name]

    # accept special keywords argument to define defaults for all operations
    # that will be processed with given by return SelfWrapper
    def __call__(self, **kwargs):
        return SelfWrapper(self.self_module, kwargs)

数行後、メインではありません

# we're being imported from somewhere
else:
    self = sys.modules[__name__]
    sys.modules[__name__] = SelfWrapper(self)
于 2013-06-27T20:23:26.073 に答える