2013-06-27 40 views
0

发现sh module整合的bash(外壳)到蟒蛇后,我使用它几乎在大多数情况下,而不是短shell脚本(SH基本上是类固醇,和这种类型的集成允许有很“Python的bash脚本“)。的确,我可以做类似导入协议:sh如何创建导入的包装函数?

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

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

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

起初,我认为有一个PEP描述这种做法作为一种“协议”(类似于__enter__()next())。但我还没有找到任何PEP解释这一点。

+0

当然,下一个问题是这样的节目是否是好还是坏的做法。我宁愿要求避免这种类型的讨论。至于我,至少在这个非常特殊的情况下,从命令行导入一些未知的事情,比如在** sh **模块的情况下,它似乎很好地实现了这个技巧,即使我们知道 >显式比隐式。 –

回答

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) 
+0

我真的很想念使用** ModuleType **的高级教程。请分享,如果你知道一个。我不知道**导入这个**是否类似? –