2015-11-02 57 views
-1

我想導入一個特殊和不尋常的模塊。爲了導入此模塊,我必須準備導入環境,導入模塊,然後在導入後再次更改環境。我能做到這一點的方法如下:函數如何設置變量的值而不返回變量的值?

argv_tmp = sys.argv 
sys.argv = [] 
from ROOT import * 
sys.argv = argv_tmp 

我想抽象周圍的實際進口到兩個功能產生以下形式的主代碼的程序:

pre_ROOT_import() 
from ROOT import * 
post_ROOT_import() 

哪有這些功能 - 不帶參數且不返回任何值的函數 - 執行這些過程?

+3

這聽起來像一個計劃很糟糕的模塊......它是公開的嗎?如果是這樣,哪一個呢? – skrrgwasme

+0

什麼阻止你只是把這些代碼行功能?你有沒有嘗試過,並得到一個錯誤或意外的行爲? – skrrgwasme

+0

使用'global'關鍵字 – tdelaney

回答

4

上下文管理器在這裏工作得很好。它將sys.argv保存在本地,並在ROOT中引發異常時恢復它。

import contextlib 
@contextlib.contextmanager 
def argv_tmp(): 
    tmp = sys.argv 
    sys.argv = [] 
    try: 
     yield 
    finally: 
     sys.argv = tmp 

with argv_tmp(): 
    from ROOT import * 
+1

我希望我能多勞多得。對於上下文管理者來說,這是一個圖片完美的用例。 – skrrgwasme

+1

這可以通過將'yield'放入'try:... finally:...'來改善,以確保在發生異常時環境仍然可以恢復。 – donkopotamus

+0

非常感謝您的解決方案。它清晰而簡潔。我認爲@MikeMüller介紹的[解決方案](http://stackoverflow.com/a/33487239/1556092)也非常好。感謝您將我介紹給背景管理員! – d3pd

0

像這樣?我認爲只需將arg_tmp拉到函數的外部就可以實現,函數仍然可以訪問它。

import sys 
argv_tmp = None 

def pre_ROOT_import(): 
    #set argv_tmp and modify sys.argv 
def post_ROOT_import(): 
    #restore sys.argv to argv_tmp 

pre_ROOT_import() 
from ROOT import * 
post_ROOT_import() 
+1

從頭開始我喜歡上下文管理器的回答 – sponrad

2

這是一個非常好的用例,用於context manager

class ArgvContext(object): 
    def __enter__(self): 
     self.tmp_argv = sys.argv 
     sys.argv = [] 
    def __exit__(self, exc_type, exc_val, exc_tb): 
     sys.argv = sys.tmp_argv 

用法:

with ArgvContext(): 
    from ROOT import * 

__enter__的代碼之前執行,並且上下文之後在__exit__的代碼。這裏的上下文只是意味着在with聲明下縮進的所有內容。使用屬性self來傳遞前後的信息。

一個簡單的例子:

class Context(object): 
    def __enter__(self): 
     print('start') 
    def __exit__(self, exc_type, exc_val, exc_tb): 
     print('end') 

with Context(): 
    print('doing') 

打印:

start 
doing 
end 

__exit__的代碼也是在一個異常的情況下執行:

with Context(): 
    1/0 

輸出:

start 
end 
--------------------------------------------------------------------------- 
ZeroDivisionError       Traceback (most recent call last) 
... 
ZeroDivisionError: division by zero 
+1

@skrrgwasme仍然在打字;)。 –

+0

非常感謝您提供非常明確,正確和詳細的答案。我討厭這個,但我必須去[這裏](http://meta.stackexchange.com/questions/13396/which-answer-do-i-accept-if-i-have-multiple-correct-answers)到如果我想接受兩個答案,試着找出該做什麼。評分最高的答案([this](http://meta.stackexchange.com/posts/13397/revisions))表明我贊成所有正確的答案並接受我實際使用的答案或首先出現的答案。我也想接受你的答案,但StackOverflow阻止我這樣做。 非常感謝! – d3pd

相關問題