0

I have two files. One is program_utils.py with the contents:

class SomeException(Exception):
    def __init__(self, *args, **kwargs):
        Exception.__init__(self, *args, **kwargs)

another, say, program.py, with

import program_utils

def SomeFunction(arg):
    if arg in set([ok_val1, ok_val2]):
        # do something
    else:
        raise SomeException('reason')

When I run program.py it complains: NameError: name 'MyException' is not defined. When I paste the contents of program_utils.py directly into program.py, it works fine. Why?

Jason
  • 884
  • 8
  • 28
  • 3
    `import program_utils` doesn't mean "dump the contents of `program_utils` into my namespace". You still have to access things as `program_utils.whatever`. – user2357112 Sep 30 '16 at 21:59
  • 2
    You didn't import the name into your namespace so you need to scope it... `program_utils.SomeException` or import into your namespace - `from program_utils import SomeException` – AChampion Sep 30 '16 at 21:59
  • This should have been obvious. Thanks for your patience everyone. – Jason Oct 01 '16 at 13:03

1 Answers1

2

Unlike #include in C/C++, in python the import statement is not equivalent to copy/pasting the file into your file.

If you want that behavior, you can sort of get it by doing:

from program_utils import *

However, there are some caveats. e.g.: if you are importing a package, the __all__ variable in the __init__.py controls which symbols get imported whtin doing from foo import *.

In general, from foo import * is not a very good practice. You don't necessarily know what symbols you are importing. Additionally you may overwrite the value of some symbols if you do that with more than one module and they both define the same symbol(s).

Arguably it is also somewhat more clear what is going on if you use the module name when using its symbols. i.e.:

foo.bar()

vs

from foo import *
...
from spam import *

bar()

In the second case it might not be obvious that bar came from the foo module.

There is a (small) performance consideration. If you end up doing foo.bar() a lot, you are actually doing an unnecessary dictionary lookup because every time, the interpreter looks up 'bar' in foo.__dict__. To fix that, you can do:

from foo import bar
Stephen
  • 2,613
  • 1
  • 24
  • 42
  • Just a note: it's a bad practice to import `*`. [Here is why](http://stackoverflow.com/questions/2386714/why-is-import-bad). – vishes_shell Sep 30 '16 at 22:08