difference between "import foo.bar" and "import foo"? - python

I just found that when I do
import pygame.joystick
I not only have access to joystick, but also to display, i.e. I can for example do
pygame.display.init()
just as if I had simply imported pygame.
What is the difference?

What's happening is that importing pygame.joystick triggers additional imports; either the pygame package itself, or pygame.joystick, or any of the pygame.* modules these two modules import, happen to import pygame.display somewhere.
So the fact that you can now reference pygame.display is an accident of implementation details. You may not be able to in future versions (if the project no longer needs to import pygame.display to load pygame.joystick, for example).
It is better to stick to an explicit import in your own project.

On import, module's inner code on the top level is executed, and the module is added to sys.modules and made available for use. Based on what was inside the source file, anything can and may happen.
In your case, either of pygame/__init__.py or pygame/joystick.py contains:
import pygame.display
Hence the availability of the module you weren't even trying to import.

In the source code of joystick, they're importing pygame.display or pygame and the sort.
In the C version of the documentation:
In the file joystick.c they've included joystick.h
#include <joystick.h>

Related

How to find everything imported by an import statement from python documentation?

I was trying to some code in python and noted this peculiar case.
import importlib
print(importlib.abc)
The above code runs fine in python 3.7 but not in python 3.10.2. In python 3.10.2, i get the following error:
AttributeError: module 'importlib' has no attribute 'abc'. Did you mean: '_abc'?
I tried to look at the documentation as to whether the behaviour of the above code got changed somehow. But couldn't find it. The documentations i tried looking are Python 3.7 importlib documentation and Python 3.10.2 importlib documentation.
So i wish to know how to find things imported by an import statement on a python standard library through documentation.
Note: I do know that i can look at dir(importlib) to see everything importlib has after it is imported. But i want to find it through documentation so i can know them without using that specific python version.
If you want to import a submodule of a package, you should do so explicitly:
import importlib.abc
Python will not automatically load all submodules of a package when you import the package. Whether submodules will be available without an explicit submodule import depends on whether some code somewhere else in the program has already loaded the module.
As for the question in the title, documentation will usually not have the information you're asking for. Good documentation will thoroughly describe a module's entire public API, but you're asking for information beyond that.
You could use python dir() function to know what importlib contains
import importlib
dir(importlib)
Or a slightly different method is hasattr(importlib,'abc') which returns a boolean.
Yet again another way is via the inspect module
import importlib
import inspect
inspect.getmembers(importlib) #Show all methods,attribute and ...
inspect.getmembers(importlib, inspect.ismodule) #Show only modules

Python import iteration, sys.path

So I was wondering, at this point in time I'm reading a book about Python. The book explains the following:
The import algorithm
To truly understand namespace packages, we have
to look under the hood to see how the import operation works in 3.3.
During imports, Python still iterates over each directory in the
module search path, sys.path, just as in 3.2 and earlier.
My question is: How is python able to iterate through sys.path when sys is not imported. Also if python is able to see sys without import to iterate through sys.path why do we need to import sys in our code?
>>> sys
NameError: name 'sys' is not defined.
>>> import sys
>>> sys
<module 'sys' (built-in)>
There's no contradiction. Python's sys module exposes the search path configurations that modifies the behaviour of import to the Python side, but even without importing sys in your Python code, the interpreter knows about its own configurations.
In the following CPython source code it is commented that
/* _PyMem_SetDefaultAllocator() is needed to get a known memory allocator,
since Py_SetPath(), Py_SetPythonHome() and Py_SetProgramName() can be
called before Py_Initialize() which can changes the memory allocator. */
What this means is that Py_SetPath(), which is responsible for setting the module search path, can be executed so early, before any Python code can be interpreted (for example, import statements), that it needs its own memory allocator before the interpreter's own memory allocator takes over.
By the time Python interpreter's main() function is run, it can already read the path configuration using Py_GetPath() that calls the internal function _PyPathConfig_Init() if necessary, which is safe to do even before the interpreter is ready to execute Python code.

importing whole python module doesn't allow using submodules

My question is specific to scikit-learn python module, but I had similar issues with matplotlib as well.
When I want to use sklearn, if I just do 'import sklearn' and then call whatever submodule I need, like ' sklearn.preprocessing.scale()', I get an error
"AttributeError: 'module' object has no attribute 'preprocessing'"
On the other hand, when I do 'from sklearn import preprocessing'
and then use 'preprocessing.scale()' it works normally.
When I use other modules like Numpy, it is sufficient to just 'import numpy' and it works well.
Therefore, I would like to ask if anyone can tell me why is this happening and if I am doing something wrong?
Thanks.
A python package is defined in the __init__.py file inside the directory.
This file determines whether or not submodules are include.
When you do import sklearn python finds the file sklearn/__init__.py and executes it to create the sklearn module. This object is the bound to the name sklearn. Submodules are not implicitly imported by the interpreter.
However when doing from sklearn import preprocessing python will first load the sklearn module as before. Then it will check if preprocessing is an attribute of that module (e.g. a function), and if not it will look for the file sklearn/preprocessing.py and improt that module too.
It happens that numpy does something like the following in its __init__.py file:
import .random
Thus when importing numpy as import numpy the execution of that module triggers the importing of numpy.random which is then added as an attribute.
This is useful because sometimes you want to use only part of a package and loading all of it could take a significant amount of time. For example importing numpy does take something like half a second. This is time wasted if you only need a very small subset of its functionality.
You may be interested in reading the documentation for packages.
Numpy conveniently imports its submodules in its __init__.py file and adds them to __all__. There's not much you can do about it when using a library - it either does it or not. sklearn apparently doesn't.

Python module dependencies

I'm trying to make my own module for easy sprite rendering & creation for personal uses. The only problem is, it needs pygame. If I were to put import pygame at the top of my module, could I then in another program, setup pygame instead of setting it up in the module? In general, does importing modules in one program, then importing that program into your main module, does the main program inherit the same dependencies, or do you need to explicitly re-import them?
Module to be used:
import pygame
def makeSprite():
# todo write code INCLUDING PYGAME DEPENDENCIES
pass
def updateSprite():
# todo write code INCLUDING PYGAME DEPENDENCIES
pass
Program using module:
import myModule # myModule is the name of the module above
pygame.init()
makeSprite(arg1, arg2)
updateSprite(arg1, arg2)
pygame.functionCallFromPygame()
Can the main program also use the module? Thank you.
That shouldn't be a problem. As long as nothing tries to actually use pygame functionality before pygame.init() is called, it'll work fine.
(In other words, as long as whatever program using your library calls pygame.init() before calling your library's functions, you'll be fine.)

__import__() calls __init__.py twice?

I was just wondering why __import__() calls a __init__ module twice when loading a package.
test.py
testpkg/
__init__.py
test.py:
pkg = __import__("testpkg", fromlist=[''])
__init__.py:
print "Called."
After calling python test.py, Called. will be printed out twice. Why does python execute the __init__ "module" twice?
This is a Python bug. Passing the null string as an element of fromlist is illegal, and should raise an exception.
There's no need to include "" in fromlist; that's implicit--the module itself is always loaded. What's actually happening is the module.submodule string is using the null string, resulting in the module name testpkg., with a trailing period. That gets imported literally, and since it has a different name than testpkg, it's imported as a separate module.
Try this:
pkg = __import__("testpkg", fromlist=[''])
import sys
print sys["testpkg"]
print sys["testpkg."]
... and you'll see the duplicate module.
Someone should probably file a ticket on this if there isn't already one; too tired to do it myself right now.
Using the fromlist=[''] hack to import a specific module is explicitly frowned upon by python-dev. While it has been filed as an issue, the chances of it being fixed are low specifically because this is viewed as a mis-use of fromlist to begin with instead of necessarily a bug and a better solution is available.
What you should be doing is using importlib.import_module (available in the standard library for Python 2.7 and Python 3.1, or from PyPI with compatibility back to Python 2.3 along with being included in Django since 1.1 as django.utils.importlib). It will prevent this problem from happening, provides a better programmatic interface for importing modules, and even lets you use relative imports when you specify the package you are importing from.
If you really cannot use importlib (e.g., PyPI dependencies are not allowed even though the code you can freely copy thanks to the PSF license and it being rather short), then you should be doing __import__("some.module"); mod = sys.modules["some.module"]. That is the official, python-dev sanctioned solution to the problem (but only after you cannot use importlib).

Categories

Resources