Как функция может установить значение переменной, не возвращая значение этой переменной?
Я хочу импортировать определенный и необычный модуль. Чтобы импортировать этот модуль, я должен подготовить среду к его импорту, импортировать модуль, а затем снова изменить среду после его импорта. Как я могу сделать это следующим образом:
argv_tmp = sys.argv
sys.argv = []
from ROOT import *
sys.argv = argv_tmp
Я хочу абстрагировать процедуры, связанные с фактическим импортом, в две функции, в результате чего основной код будет иметь следующую форму:
pre_ROOT_import()
from ROOT import *
post_ROOT_import()
Как эти функции - функции, которые не принимают аргументов и не возвращают значений - могут выполнять эти процедуры?
3 ответа
Здесь хорошо работает контекстный менеджер. Он локально хранит 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 *
Это очень хороший вариант использования для менеджера контекста.
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
Что-то вроде этого? Я думаю, что просто потянув 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()