简体   繁体   中英

Confused why import os; os.environ['a'] = 'x'; import os.path raises UnboundLocalError

Can someone explain why the following happens? I had a look at Should I use `import os.path` or `import os`? which is informative, vaguely similar, but didn't really clarify it for me.

If I comment out import os.path or add it directly after import os there's no error.

$ 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
$

Because an import is also an assignment. If you do import os.path in your main method, you're making os a local name, and Python won't look in the global scope to see the os you've already imported.

# 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 does two things. First, it creates a module object. Second it gives a name to that newly created module object. Giving something a name is assignment, hence the error message " UnboundLocalError: local variable 'os' referenced before assignment ".

Python has rules about the visibility of names and when they can be referenced. One of the rules is that there cannot be ambiguity in a function as to whether you mean to refer to a local name or a global name. If a local name is created anywhere inside a function that is the same as a global name, Python assumes that all references to that name inside the function refer to the local name (unless you specifically say otherwise).

Three possible fixes.

Drop the local import:

import os

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

Drop the global import and move local import to the top of the function

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

Declare os global at the beginning of your function so that the first reference uses the global:

import os

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

A note about imports.

# 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

I happens because you are trying to use the library 'os' before importing it. You can do

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()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM