Reputation: 1310
Similar Question: Understanding A Chain of Imports in Python
NB: I'm using Python 3.3 I have setup the following two files in the same directory to explain importing to myself, however I still don't get exactly what it's doing. I understand function and class definitions are statements that need to run.
untitled.py:
import string
class testing:
def func(self):
try:
print(string.ascii_lowercase)
except:
print('not imported')
class second:
x=1
print('print statement in untitled executed')
stuff.py:
from untitled import testing
try:
t=testing()
t.func()
except NameError:
print('testing not imported')
try:
print(string.ascii_uppercase)
except NameError:
print('string not imported')
try:
print(untitled.string.ascii_uppercase)
except NameError:
print('string not imported in untitled')
try:
s=second()
print(s.x)
except NameError:
print('second not imported')
This is the output I get from running stuff.py:
print statement in untitled executed
abcdefghijklmnopqrstuvwxyz
string not imported
string not imported in untitled
second not imported
The print statement in untitled.py is executed despite the import in stuff.py specifying only the testing class. Moreover what is the string module's relation inside stuff.py, as it can be called from within the testing class yet not from the outside.
Could somebody please explain this behaviour to me, what exactly does a "from import" statment do (what does it run)?
Upvotes: 2
Views: 144
Reputation: 77241
You can think of python modules as namespaces. Keep in mind that imports are not includes:
Suppose you have a module called foo.py
:
import eggs
bar = "Lets drink, it's a bar'
So when you do a from foo import bar
in another module, you will make bar
available in the current namespace. The module eggs
will be available under foo.eggs
if you do an import foo
. If you do a from foo import *
, then eggs
, bar
and everything else in the module namespace will be also in the current namespace - but never do that, wildcard imports are frowned upon in Python.
If you do a import foo
and then import eggs
, the top level code at eggs
will be executed once and the module namespace will be stored in the module cache: if another module imports it the information will be pulled from this cache. If you are going to use it, then import it - no need to worry about multiple imports executing the top level code multiple times.
Python programmers are very fond of namespaces; I always try to use import foo
and then foo.bar
instead of from foo import bar
if possible - it keeps the namespace clean and prevent name clashes.
That said, the import mechanism is hackable, you can make python import
statement work even with files that are not python.
Upvotes: 2
Reputation: 35891
The from
statement isn't any different to import
with regard to loading behaviour. Always the top level code is executed, when loading the module. from
just controls which parts of the loaded module are being added to the current scope (the first point is most important):
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
- if the attribute is not found, ImportError is raised.
- otherwise, a reference to that value is bound in the local namespace, using the name in the as clause if it is present, otherwise using the attribute name
Thus you can access the contents of a module partially imported with from
with this inelegant trick:
print(sys.modules['untitled'].string.ascii_uppercase)
Upvotes: 1
Reputation: 813
In your first file (untitled.py), when python compiler parses(since you called it in import) this file It will create 2 class code objects and execute the print statement. Note that it will even print it if you run untitled.py from command line.
In your second file(stuff.py), to add to @Paulo comments, you have only imported testing class in your namspace, so only that will be available, from the 2 code objects from untitled.py However if you just say
import untitled
your 3rd "try" statement will work, since it will have untitled in its namespace.
Next thing. try importing untitled.testing :)
Upvotes: 0