我想导入一个特殊且不寻常的模块。为了导入此模块,我必须为其导入准备环境,导入模块,然后在导入后再次更改环境。我可以这样做的方式如下:
argv_tmp = sys.argv
sys.argv = []
from ROOT import *
sys.argv = argv_tmp
我想将实际导入的过程抽象为两个函数,从而产生以下形式的主代码:
pre_ROOT_import()
from ROOT import *
post_ROOT_import()
这些函数如何 - 不带参数且不返回值的函数 - 执行这些过程?
答案 0 :(得分: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 :(得分: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
答案 2 :(得分: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()