Exception Class Failed to Import - python

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?

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

Related

Python how to use function in imported file defined in importing file?

Sometimes, I see examples like this, but I don't understand how do they work. Imported module uses function without any places in which this function is set to use. Please can someone explain me how to use them.
Example:
from some_package import *
def some_func():
# do_something
pass
imported_func()
And then imported_func somehow defines some_func and uses it. How is this implemented?
When I tried to call some_func from module.py I received an error. Again: idea is to use function from imported file which was defined in importing file. I couldn't find answer in google.
I tried:
from f.module import *
obj = cls()
def some_func():
for _ in range(100):
print("smth")
obj.imported_func()
Code in main.py
class cls:
#staticmethod
def imported_func():
some_func()
Code in module.py
I have main.py and folder f in one directory. In folder f I have module.py
The way to do this is at first import __main__ then call __main__.some_func(), but remember, it's not a good practice because at least you are reserving name, what can become common reason for errors.

Import symbols starting with underscore

I'm writing a simple Python library in which I have several "private" functions starting with underscore:
def _a():
pass
def _b():
pass
def public_interface_call():
_a()
_b()
This way my library users can simply do from MyLib.Module import * and their namespace won't be cluttered with implementation detail.
However I'm also writing unit tests in which I'd love to test these functions separately and simple importing truly all symbols from my module would be very handy. Currently I'm doing from Mylib.Module import _a _b public_interface_call but I wonder if there's any better/quicker/cleaner way to achieve what I want?
I'm not sure if it was a blackout or something when I wrote that question but today I realized (inspired by Underyx's comment) that I can simply do this:
import MyLib.Module
MyLib.Module._a()
MyLib.Module._b()
Or even to shorten things a little (because I'm a lazy bastard):
import MyLib.Module as mm
mm._a()
mm._b()
According to docs,
There is even a variant to import all names that a module defines:
from fibo import *
...
This imports all names except those beginning with an underscore (_).
Not sure why this is the case however.
The best and most common solution for your problem already has been given:
import MyLib.Module as mm
If one still wants to make use of the variant from MyLib.Module import *, there is the possibility to override its default behavior: Add a list __all__ to the module's source file MyLib/Module.py and declare which objects should be exported.
Note that you need to do this for every object you want to be visible. This does not affect the behavior of the other import mechanism above.
Example:
# MyLib/Module.py
__all__ = ["_a", "_b"]
def _a(): pass
def _b(): pass
def c(): pass
# ...
# Import
from MyLib.Module import *
# => this imports _a() and _b(), but not c()
To specify a package index __all__ can make sense to control which submodules should be loaded when importing a package. See here for more information, or this SO thread on a related question.

Why can't Python's import work like C's #include?

I've literally been trying to understand Python imports for about a year now, and I've all but given up programming in Python because it just seems too obfuscated. I come from a C background, and I assumed that import worked like #include, yet if I try to import something, I invariably get errors.
If I have two files like this:
foo.py:
a = 1
bar.py:
import foo
print foo.a
input()
WHY do I need to reference the module name? Why not just be able to write import foo, print a? What is the point of this confusion? Why not just run the code and have stuff defined for you as if you wrote it in one big file? Why can't it work like C's #include directive where it basically copies and pastes your code? I don't have import problems in C.
To do what you want, you can use (not recommended, read further for explanation):
from foo import *
This will import everything to your current namespace, and you will be able to call print a.
However, the issue with this approach is the following. Consider the case when you have two modules, moduleA and moduleB, each having a function named GetSomeValue().
When you do:
from moduleA import *
from moduleB import *
you have a namespace resolution issue*, because what function are you actually calling with GetSomeValue(), the moduleA.GetSomeValue() or the moduleB.GetSomeValue()?
In addition to this, you can use the Import As feature:
from moduleA import GetSomeValue as AGetSomeValue
from moduleB import GetSomeValue as BGetSomeValue
Or
import moduleA.GetSomeValue as AGetSomeValue
import moduleB.GetSomeValue as BGetSomeValue
This approach resolves the conflict manually.
I am sure you can appreciate from these examples the need for explicit referencing.
* Python has its namespace resolution mechanisms, this is just a simplification for the purpose of the explanation.
Imagine you have your a function in your module which chooses some object from a list:
def choice(somelist):
...
Now imagine further that, either in that function or elsewhere in your module, you are using randint from the random library:
a = randint(1, x)
Therefore we
import random
You suggestion, that this does what is now accessed by from random import *, means that we now have two different functions called choice, as random includes one too. Only one will be accessible, but you have introduced ambiguity as to what choice() actually refers to elsewhere in your code.
This is why it is bad practice to import everything; either import what you need:
from random import randint
...
a = randint(1, x)
or the whole module:
import random
...
a = random.randint(1, x)
This has two benefits:
You minimise the risks of overlapping names (now and in future additions to your imported modules); and
When someone else reads your code, they can easily see where external functions come from.
There are a few good reasons. The module provides a sort of namespace for the objects in it, which allows you to use simple names without fear of collisions -- coming from a C background you have surely seen libraries with long, ugly function names to avoid colliding with anybody else.
Also, modules themselves are also objects. When a module is imported in more than one place in a python program, each actually gets the same reference. That way, changing foo.a changes it for everybody, not just the local module. This is in contrast to C where including a header is basically a copy+paste operation into the source file (obviously you can still share variables, but the mechanism is a bit different).
As mentioned, you can say from foo import * or better from foo import a, but understand that the underlying behavior is actually different, because you are taking a and binding it to your local module.
If you use something often, you can always use the from syntax to import it directly, or you can rename the module to something shorter, for example
import itertools as it
When you do import foo, a new module is created inside the current namespace named foo.
So, to use anything inside foo; you have to address it via the module.
However, if you use from from foo import something, you don't have use to prepend the module name, since it will load something from the module and assign to it the name something. (Not a recommended practice)
import importlib
# works like C's #include, you always call it with include(<path>, __name__)
def include(file, module_name):
spec = importlib.util.spec_from_file_location(module_name, file)
mod = importlib.util.module_from_spec(spec)
# spec.loader.exec_module(mod)
o = spec.loader.get_code(module_name)
exec(o, globals())
For example:
#### file a.py ####
a = 1
#### file b.py ####
b = 2
if __name__ == "__main__":
print("Hi, this is b.py")
#### file main.py ####
# assuming you have `include` in scope
include("a.py", __name__)
print(a)
include("b.py", __name__)
print(b)
the output will be:
1
Hi, this is b.py
2

Is there a way to bypass the namespace/module name in Python?

If you have a module like module, can you bypass it and use the functions available inside without using the module?
I imported the module, but the compiler still complains not having to find function. I still have to use module.function().
It has many more functions, so I don't want to redefine them one by one but just avoid typing module if possible.
Importing in Python just adds stuff to your namespace. How you qualify imported names is the difference between import foo and from foo import bar.
In the first case, you would only import the module name foo, and that's how you would reach anything in it, which is why you need to do foo.bar(). The second case, you explicitly import only bar, and now you can call it thus: bar().
from foo import * will import all importable names (those defined in a special variable __all__) into the current namespace. This, although works - is not recommend because you may end up accidentally overwriting an existing name.
foo = 42
from bar import * # bar contains a `foo`
print foo # whatever is from `bar`
The best practice is to import whatever you need:
from foo import a,b,c,d,e,f,g
Or you can alias the name
import foo as imported_foo
Bottom line - try to avoid from foo import *.

Is there a reason why when importing python files, you still need to name the file.function_name?

I am currently doing a python tutorial, but they use IDLE, and I opted to use the interpreter on terminal. So I had to find out how to import a module I created. At first I tried
import my_file
then I tried calling the function inside the module by itself, and it failed. I looked around and doing
my_file.function
works. I am very confused why this needs to be done if it was imported. Also, is there a way around it so that I can just call the function? Can anyone point me in the right direction. Thanks in advance.
If you wanted to use my_file.function by just calling function, try using the from keyword.
Instead of import my_file try from my_file import *.
You can also do this to only import parts of a module like so :
from my_file import function1, function2, class1
To avoid clashes in names, you can import things with a different name:
from my_file import function as awesomePythonFunction
EDIT:
Be careful with this, if you import two modules (myfile, myfile2) that both have the same function inside, function will will point to the function in whatever module you imported last. This could make interesting things happen if you are unaware of it.
This is a central concept to python. It uses namespaces (see the last line of import this). The idea is that with thousands of people writing many different modules, the likelihood of a name collision is reasonably high. For example, I write module foo which provides function baz and Joe Smith writes module bar which provides a function baz. My baz is not the same as Joe Smiths, so in order to differentiate the two, we put them in a namespace (foo and bar) so mine can be called by foo.baz() and Joe's can be called by bar.baz().
Of course, typing foo.baz() all the time gets annoying if you just want baz() and are sure that none of your other modules imported will provide any problems... That is why python provides the from foo import * syntax, or even from foo import baz to only import the function/object/constant baz (as others have already noted).
Note that things can get even more complex:
Assume you have a module foo which provides function bar and baz, below are a few ways to import and then call the functions contained inside foo...
import foo # >>> foo.bar();foo.baz()
import foo as bar # >>> bar.bar();bar.baz()
from foo import bar,baz # >>> bar(); baz()
from foo import * # >>> bar(); baz()
from foo import bar as cow # >>> cow() # This calls bar(), baz() is not available
...
A basic import statement is an assignment of the module object (everything's an object in Python) to the specified name. I mean this literally: you can use an import anywhere in your program you can assign a value to a variable, because they're the same thing. Behind the scenes, Python is calling a built-in function called __import__() to do the import, then returning the result and assigning it to the variable name you provided.
import foo
means "import module foo and assign it the name foo in my namespace. This is the same as:
foo = __import__("foo")
Similarly, you can do:
import foo as f
which means "import module foo and assign it the name f in my namespace." This is the same as:
f = __import__("foo")
Since in this case, you have only a reference to the module object, referring to things contained by the module requires attribute access: foo.bar etc.
You can also do from foo import bar. This creates a variable named bar in your namespace that points to the bar function in the foo module. It's syntactic sugar for:
bar = __import__("foo").bar
I don't really understand your confusion. You've imported the name my_file, not anything underneath it, so that's how you reference it.
If you want to import functions or classes inside a module directly, you can use:
from my_file import function
I'm going to incorporate many of the comments already posted.
To have access to function without having to refer to the module my_file, you can do one of the following:
from my_file import function
or
from my_file import *
For a more in-depth description of how modules work, I would refer to the documentation on python modules.
The first is the preferred solution, and the second is not recommended for many reasons:
It pollutes your namespace
It is not a good practice for maintainability (it becomes more difficult to find where specific names reside.
You typically don't know exactly what is imported
You can't use tools such as pyflakes to statically detect errors in your code
Python imports work differently than the #includes/imports in a static language like C or Java, in that python executes the statements in a module. Thus if two modules need to import a specific name (or *) out of each other, you can run into circular referencing problems, such as an ImportError when importing a specific name, or simply not getting the expected names defined (in the case you from ... import *). When you don't request specific names, you don't run into the, risk of having circular references, as long as the name is defined by the time you actually want to use it.
The from ... import * also doesn't guarantee you get everything. As stated in the documentation on python modules, a module can defined the __all__ name, and cause from ... import * statements to miss importing all of the subpackages, except those listed by __all__.

Categories

Resources