1

在发现sh module将 bash(shell)集成到 python 之后,我几乎在大多数情况下都使用它而不是短 shell 脚本(sh基本上是类固醇的进程,这种类型的集成允许非常“pythonic bash 脚本”)。确实,我可以做类似的事情

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

现在ifconfig不是 sh 模块的一部分。显然,这个函数是动态构造的。现在我非常好奇这是如何完成的。

所以,我的问题是它是如何工作的?

起初我以为有一个 PEP 将这种做法描述为一种“协议”(类似于__enter__()or 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 回答