package imports libraries without even intializing class - python

The doubt is the if import a class from a package inside another package like this :
from bar import foo
Does it initialize the class? and if the module has an import at the first line like :
import tensorflow
class foo:
def __init__(self):
# some things
Does it import the package even if we don't initialize the class from another file?

Does it initialize the class?
No, it just gives your program access to that class - ready to be instantiated to an object when you want to (then it will call the __init__ method).
Does it import the package even if we don't initialize the class from another file?
Yes. You can see this as if you were to just import bar, then you would be able to access the imported tensorflow module with bar.tensorflow, i.e. it is actually imported even if there is nothing else in the module.
In your specific case of just importing foo from bar, we can still access tensorflow via the inspect built-in package that will give us a reference to bar and thus .tensorflow from foo.
import inspect
from bar import foo
print(inspect.getmodule(foo).itertools) #<module 'itertools' (built-in)>
I'm not sure if there is an easier way to "get at" bar from foo without using inspect, but this is what I found for the purpose of explaining your case fully!

Related

Is there a difference between following import styles in python? [duplicate]

Should I use
from foo import bar
OR
import foo.bar as bar
when importing a module and and there is no need/wish for changing the name (bar)?
Are there any differences? Does it matter?
Assuming that bar is a module or package in foo, there is no difference*, it doesn't matter. The two statements have exactly the same result:
>>> import os.path as path
>>> path
<module 'posixpath' from '/Users/mj/Development/venvs/stackoverflow-2.7/lib/python2.7/posixpath.pyc'>
>>> from os import path
>>> path
<module 'posixpath' from '/Users/mj/Development/venvs/stackoverflow-2.7/lib/python2.7/posixpath.pyc'>
If bar is not a module or package, the second form will not work; a traceback is thrown instead:
>>> import os.walk as walk
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named walk
* In Python 3.6 and before, there was a bug with the initialization ordering of packages containing other modules, where in the loading stage of the package using import contained.module.something as alias in a submodule would fail where from contained.module import something as alias would not. See Imports in __init__.py and `import as` statement for a very illustrative example of that problem, as well as Python issues #23203 and #30024.
This is a late answer, arising from what is the difference between 'import a.b as b' and 'from a import b' in python
This question has been flagged as a duplicate, but there is an important difference between the two mechanisms that has not been addressed by others.
from foo import bar imports any object called bar from namespace foo into the current namespace.
import foo.bar as bar imports an importable object (package/module/namespace) called foo.bar and gives it the alias bar.
What's the difference?
Take a directory (package) called foo which has an __init__.py containing:
# foo.__init__.py
class myclass:
def __init__(self, var):
self.__var = var
def __str__(self):
return str(self.__var)
bar = myclass(42)
Meanwhile, there is also a module in foo called bar.py.
from foo import bar
print(bar)
Gives:
42
Whereas:
import foo.bar as bar
print(bar)
Gives:
<module 'foo.bar' from '/Users//..../foo/bar.py'>
So it can be seen that import foo.bar as bar is safer.
Both are technically different:
import torch.nn as nn will only import a module/package torch.nn, wheres
from torch import nn can and will prefer to import an attribute .nn from the torch module/package. Importing a module/package torch.nn is a fall.back.
In practice, it is bad style to have the same fully qualified name refer to two separate things. As such, torch.nn should only refer to a module/package. In this common case, both import statements are functionally equivalent: The same object is imported and bound to the same name.
Which one to choose comes down to preference if the target always is a module. There are practical differences when refactoring:
import torch.nn as nn guarantees .nn is a module/package. It protects against accidentally shadowing with an attribute.
from torch import nn does not care what .nn is. It allows to transparently change the implementation.
7.11. The import statement
The basic import statement (no from clause) is executed in two steps:
find a module, loading and initializing it if necessary
define a name or names in the local namespace for the
scope where the import statement occurs.
[...]
The from form uses a slightly more complex process:
find the module specified in the from clause, loading and initializing it if necessary;
for each of the identifiers specified in the import clauses:
check if the imported module has an attribute by that name
if not, attempt to import a submodule with that name and then check the imported module again for that attribute
You can use as to rename modules suppose you have two apps that have views and you want to import them
from app1 import views as views1
from app2 import views as views2
if you want multiple import use comma separation
>>> from datetime import date as d, time as t
>>> d
<type 'datetime.date'>
>>> t
<type 'datetime.time'>
The only thing I can see for the second option is that you will need as many lines as things you want to import. For example :
import foo.bar as bar
import foo.tar as tar
import foo.zar as zar
Instead of simply doing :
from foo import bar, tar, zar
The difference between import module and from module import is mainly subjective. Pick the one you like best and be consistent in your use of it. Here are some advantage of both to help you decide.
advantage of import
Less maintenance of your import statements.
Don't need to add any additional imports to start using another item from the module
advantage of from torch import nn
Less typing to use the nn
More control over which items of a module can be accessed

Equivalent to 'from module import *' but including private members

I have a git repo that has a python module defining a few classes, some of which are private. I'm using that git repo as a git submodule elsewhere and want to add a new python module with the same name and a few more classes.
The idea is something like:
repo1/module.py:
class _foo:
def __init__(self, _arguments_):
#dostuff
class bar(_foo):
def __init__(self, _arguments_):
#dostuff
repo2/module.py:
class baz(_foo):
def __init__(self, _arguments_):
#dostuff
What I'm stuck on is how to correctly handle the importing in repo2/module.py so that I can use _foo as the super for baz, but also allow importing of repo2/module to provide access to bar.
If I start repo2/module.py with:
from repo1.module import *
I don't get _foo available to use as a super, but I do get bar available when repo2/module.py is imported elsewhere. On the other hand I could do:
from repo1 import module as mod
and then I have mod._foo available to use as the super, but I don't get bar available for use elsewhere.
Is there a way to do something equivalent to
from module import *
that also includes private members, or should I do something like
from module import *
from module import _foo
or is there something nicer/better/safer/cleaner? If it makes a difference, I dislike from module import * and would prefer to avoid it if possible.

Why are imported packages visible inside other packages?

If I create a package named foo that imports bar, why is bar visible under foo as foo.bar when I import foo in another module? Is there a way to prevent this; to keep bar hidden so as not to clutter the namespace?
Import bar wherever you use it, rather than globally
If bar is being used in a function, import as
def func():
import bar
....
Or even,
if __name__ == '__main__':
import bar
my_main(bar)
Or if you love classes,
class Fubar():
def __init__(self):
import bar
self.bar = bar
Imports in Python are really just another form of name assignment. There is really no difference between an object that has been imported into foo and one that has been defined in foo - they are both visible internally and externally in exactly the same way. So no, there is no way to prevent this.
I don't really see how this is cluttering the namespace, though. You've still only imported one name, foo, into your other module.
TL;DR: Python Imports create named bindings for pieces of code so they can be referenced and used.
An import is essentially binding a piece of code to a name. So the namespace should always reflect what has been imported. If you hide that you may end up causing unexpected problems for someone else or yourself.
If you are importing the wrong modules, importing modules you don't use, or have a ton of imports because you have 10 classes in one file you should consider fixing the underlying issue(s). Not trying to hide it by messing with how modules are imported.

Does Python import instantiate a mystery class?

I thought about this for a while and can't think of a better title, sorry.
I'm new'ish to Python, and (like many other's it seems) I just can't get my head around import.
I think I understand 'modules' and 'packages', classes and attributes and all that. It's one specific behavior I need clarified.
Say I have a file, foo.py. It has one line it:
x = 1
If, in another file, I `import foo", I can reference x. And, wonderfully, in another file I can import foo and now those two files can share x. Leaving classes out of the discussion for simplicity, I believe this is the pythonic way to share attributes between files.
Here's the question: Is is fair to say, when I import foo, that foo.py itself is, (for lack of a better metaphor), secretly instantiated by the interpreter?
I realize if I define a class in a module, it follow traditional rules and only become instantiated if I explicitly do so. But, the python interpreter (via the import statement) instantiating an instance of my module in the global namespace is the only way to explain the attribute sharing behavior.
Is this true? Semi-true? Or am I wandering with the Sleestaks in the Land of the Lost?
When you import a module:
if the module has not been previously imported, the file is parsed in to a module object which is added to sys.modules with a key that is the import path from the pythonpath to your module
that module object (or some member thereof) is aliased in the importing namespace, the alias and object being referenced being determined by the specific form of import you used
So when you import foo, the interpreter checks sys.modules for something registered with the name foo. If it finds it, it provides a label foo in the local namespace for the foo module. If it doesn't, it searches down the pythonpath until it finds a foo module, parses that to a module object, adds that object to sys.modules, and adds a label in the local namespace for that module object.
import foo as foof does the same thing, only the local namespace label created is foof. from foo import x follows the same process up to the point of creating a label and reference in the local namespace, instead providing a label x in the namespace for the attribute x from the foo module. from foo import x as foox just combines the 2 ideas.
With classes, you can actually poke around this whole system by crawling up and down the tree using the __module__ attribute.
The import creates an instance of a "module" object. It is worth knowing that this is created only the first time the module is imported. The following times it is imported you are getting a reference to the original. You can create your own module objects on the fly with a bit of instrospection.
import glob # Import any python module
moduleType = type(glob)
onTheFly = moduleType("OnTheFly", "Docstring for this module")
Although there isn't much benefit to creating these.
Yes, indeed its true. If you execute import foo a module object foo is instatiated and the contents of your file e.g a class bar is added as a member of that object.

How do I make classes from a submodule available in a parent module's namespace?

Here's a python module. foo is in sys.path.
foo\
__init__.py
bar\
__init__.py
base.py
class Base(object)
derived.py
import foo.bar.base as base
class Derived(base.Base)
I've got nothing fancy going on yet. If I want to instantiate the Derived class from the derived module, I can do that easily enough:
import foo.bar.derived as derived
print(derived.Derived())
However, I'd like to just import the bar module and call bar.Derived(), because I plan to have lots of classes within lots of different modules, and I don't want to deal with all these tentacular import paths. My understanding is that I can simply import Derived into the namespace of the bar module, by modifying my project like so:
foo\
__init__.py
bar\
__init__.py
from foo.bar.derived import Derived
base.py
class Base(object)
derived.py
import foo.bar.base as base
class Derived(base.Base)
Now I should be able to do the following:
import foo.bar as bar
print(bar.Derived())
But I get an AttributeError complaining that the foo module has no submodule called bar:
test.py (1): import foo.bar
foo\bar\__init__.py (1): from foo.bar.derived import Derived
foo\bar\derived.py (1): import foo.bar.base as base
AttributeError: 'module' object has no attribute 'bar'
In fact, my original test code (at top) doesn't work either! As soon as I try to import foo.bar, I get errors.
What I can gleam from this error is that the import statement in __init__.py causes derived.py to be executed before bar is fully loaded, and therefore it can't import the module (also from bar) which contains its own base class. I'm coming from the C++ world, where ultra-nested namespaces aren't as integral and a simple forward declaration would negate this problem, but I've been led to believe that what I'm looking for is possible and at least a somewhat acceptably Pythonic solution. What am I doing wrong? What's the correct way to make classes from a submodule available in the parent module's namespace?
If you're working with Python 2.5 or later, try using explicit relative imports (http://www.python.org/dev/peps/pep-0328/#guido-s-decision):
test.py (1): import foo.bar
foo\bar\__init__.py (1): from .derived import Derived
foo\bar\derived.py (1): from . import base
(Note that if you are indeed working with Python 2.5 or 2.6, you'll need to include from __future__ import absolute_import in your modules.)
in derived.py, use this:
EDIT: as JAB pointed out, implicit relative imports are deprecated, to the following isn't recommended (although it does work still in Python 2.7 - with no deprecation errors!).
import base # this is all you need - it's in the current directory
Instead, use:
from . import base #
(or)
from foo.bar import base
instead of:
import foo.bar.base as base
This will solve both your errors (since they're from the same issue). Your import doesn't work since there is no base function or class inside the foo.bar.base module.

Categories