2017-02-17 46 views
0

Может кто-нибудь объяснить, почему происходит следующее? Я взглянул на Should I use `import os.path` or `import os`?, который является информативным, смутно похожим, но на самом деле не прояснил его для меня.Confused почему import os; os.environ ['a'] = 'x'; import os.path повышает UnboundLocalError

Если я прокомментирую import os.path или добавьте его непосредственно после import os, нет ошибок.

$ python -V 
Python 2.7.2 
$ cat min.py 
import os 

def main(): 
    os.environ['blah'] = 'bloo' 
    import os.path 


if __name__ == '__main__': 
    main() 
$ python min.py 
Traceback (most recent call last): 
    File "min.py", line 9, in <module> 
    main() 
    File "min.py", line 4, in main 
    os.environ['blah'] = 'bloo' 
UnboundLocalError: local variable 'os' referenced before assignment 
$ 
+0

Не уверен, но я подозреваю, что «импорт os.path» рассчитывает как записи в 'os' переменной в локальной области видимости, поэтому' os' не существует до того, что (который, кажется, как ошибка для меня, что os считается здесь присвоением). 'os.path' должен быть целью назначения. – Max

ответ

2
# assigns 'os' to global namespace 
import os 

def main(): 
    os.environ['blah'] = 'bloo' # <== which 'os'? python assumes local 
    # assigns 'os' to local namespace 
    import os.path 

import делает две вещи. Во-первых, он создает объект модуля. Во-вторых, он дает имя для вновь созданного объекта модуля. Предоставление чего-то имени является присвоением, поэтому появляется сообщение об ошибке «UnboundLocalError: local variable 'os' referenced before assignment».

У Python есть правила, касающиеся видимости имен и ссылок на них. Одно из правил заключается в том, что не может быть двусмысленности в функции относительно того, хотите ли вы ссылаться на локальное имя или глобальное имя. Если локальное имя создается где-либо внутри функции, которая совпадает с глобальным именем, Python предполагает, что все ссылки на это имя внутри функции ссылаются на локальное имя (если вы не указали иное).

Три возможных исправления.

падение местный импорт:

import os 

def main(): 
    os.environ['blah'] = 'bloo' 

падение глобального импорта и переместить местный импорт в верхней части функции

def main(): 
    import os.path 
    os.environ['blah'] = 'bloo' 

Declare os глобальной в начале вашей функции, так что первая ссылка использует глобальное:

import os 

def main(): 
    global os 
    os.environ['blah'] = 'bloo' 
    import os.path 

A не е об импорте.

# has the same effect as 'import module' 
# creates a reference named 'module' 
import module.submodule 

# imports submodule and creates a reference to it named 'submodule' 
from module import submodule 

# imports submodule and creates a reference to it named 'x' 
import module.submodule as x 
0

Это случается, потому что вы пытаетесь использовать библиотеку «os» перед импортом. Вы можете сделать

def main(): 
    import os 
    #now you can use os.environment 
    os.environ['blah'] = 'bloo' 
    #you don't need to import os.path as os is already imported 


if __name__ == '__main__': 
    main() 
+0

Это «import os.path» после назначения, вызывающего проблемы. В вашем примере, если я переведу 'import os' в глобальный охват, все будет hunky dory. Я согласен с тем, что мне технически не нужно «импортировать os.path» в любом случае, но мне любопытно, почему это проблема. – jones77

4

Поскольку импорт также присваивание. Если вы делаете import os.path в своем основном методе, вы делаете osлокальным именем, а Python не будет искать в глобальной области видимости os, которую вы уже импортировали.

+0

Очень красно. Вы говорите в двух предложениях, что мне понадобилось десять. –

+1

Стив прав, что это самый лучший ответ, но объяснение Стива помогло мне понять это в моей голове: «У Python есть правила о видимости имен и когда их можно называть. Одно из правил заключается в том, что не может быть двусмысленности в функции относительно того, хотите ли вы ссылаться на локальное имя или глобальное имя.Если локальное имя создается где-нибудь внутри функции, которая совпадает с глобальным именем, Python предполагает, что все ссылки на это имя внутри функции ссылаются на локальное имя (если вы не указали иное). » Спасибо вам обоим. – jones77