Как функция может установить значение переменной, не возвращая значение этой переменной?

Я хочу импортировать определенный и необычный модуль. Чтобы импортировать этот модуль, я должен подготовить среду к его импорту, импортировать модуль, а затем снова изменить среду после его импорта. Как я могу сделать это следующим образом:

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()
Другие вопросы по тегам