2013-06-27 41 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 **的高級教程。請分享,如果你知道一個。我不知道**導入這個**是否類似? –