UnboundLocalError после попытки импорта из необязательной зависимости - PullRequest
0 голосов
/ 09 июля 2020

Ниже приведен минимальный код для восстановления ошибки

def foo(): 
    # hard code implementation
    pass

def func(): 
    try:
        from scipy import foo # unsuccess here
    except: 
        ...

    foo()

func()

Ошибка

UnboundLocalError: local variable 'foo' referenced before assignment

Моя мотивация :

По сути, здесь я ' m пытается вызвать эту функцию foo(). Я заметил, что scipy может уже реализовать это. Поскольку scipy настолько тяжелый, я бы хотел избежать make scipy в качестве зависимости. Тем не мение. если пользователь иногда уже установил scipy, я хотел бы импортировать метод из scipy и использовать его. Если пользователь этого не сделает, ничего страшного. Я уже жестко запрограммировал функцию foo для вас.

Вопрос : Почему срабатывает UnboundLocalError? Есть ли что-то под капотом import?

Здесь foo и scipy - всего лишь примеры, чтобы убедиться, что импорт завершился неудачно.

1 Ответ

1 голос
/ 09 июля 2020

Простого наличия оператора import в func (независимо от того, успешно он или нет) достаточно, чтобы генератор кода сделал foo локальным именем. (Оператор import - это своего рода причудливый оператор присваивания). В результате он не будет возвращаться к глобальной переменной с тем же именем, даже если переменная с таким именем не определена.

Чтобы foo продолжал работать в случае сбоя import , объявите foo глобальным.

def foo(): 
    # hard code implementation
    pass

def func(): 
    <b>global foo</b>
    try:
        from scipy import foo # unsuccess here
    except: 
        ...

    foo()

func()

Вы можете заметить разницу, поместив свой код в файл tmp.py и запустив python -mdis tmp.py с оператором global и без него. Без global вы увидите использование STORE_NAME, STORE_FAST и LOAD_FAST, поскольку решение об использовании локальной переменной должно быть принято до того, как код сможет фактически выполняться.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...