Python¶
Absolute and Relative Imports¶
Say, we have the following project layout:
.
├── foo
│ ├── __init__.py
│ ├── mod1.py
│ └── mod2.py
└── main.py
mod1.py contains:
import mod2
main.py contains:
from foo import mod1
If you try to do
$ python3 main.py
from the project root, the ModuleNotFoundError: No module named 'mod2'
exception will be raised.
That’s because in Python 3 imports are absolute. Or, as PEP 328
states, modules are searched in sys.path only.
The current directory is added to sys.path automatically, thus the
foo package is reachable from main.py. However, as soon as Python
tries to import mod2 from inside mod1 it fails because there is no
such module in the project root which is the current directory.
The fact that the current directory is added to sys.path automatically, can
be a source of subtle bugs. Imagine, for example, that you have developed the
foo package separately. Things like python3 mod1.py worked perfectly
when you run them from inside foo. Now you try to use the foo package
in another project and, yes, ModuleNotFoundError.
There are several ways to fix the issue:
Fully qualify the import statement inside
mod1.py:import foo.mod2
or to
from foo import mod2
Both work because
foois insys.path.Use the relative import in
mod1.py:from . import mod2
Explicitly add the
foodirectory toPYTHONPATHbefore run:$ PYTHONPATH=foo python3 main.py
Warning
For a relative import it’s tempting to do import .mod2 but it’s
an illegal syntax!
In Python 2 imports, are relative by default, so the python2 main.py
command finishes successfully. Again, this is because in Python 2 the
import mod2 statement equals to from . import mod2. The Python 3
behavior in Python 2 can be enabled with the from __future__ import
absolute_import statement at the beginning of a module.
Summing up, the absolute import approach makes it virtually possible to forget
about everything but sys.path when dealing with imports. So, when you see
something like
import some_module
you know exactly that some_module should be in sys.path.
Threading¶
Dummy Threads¶
Dummy threads, which are instances of the threading._DummyThread
class, are used for representing threads not created by the means of the
threading module.
If you call the current_thread() in such thread, it will
return a dummy thread object. After the call, the thread will be added to the
internal dictionary of active threads and functions such as
enumerate() and active_count() will become aware of it.
A short example to illustrate said above:
import threading
import time
from _thread import start_new_thread
def func():
threading.current_thread()
return 42
if __name__ == '__main__':
start_new_thread(func, ())
time.sleep(0.5) # give the dummy thread some time to finish
print(threading.active_count())
print(threading.enumerate())
The example prints the following:
2
[<_MainThread(MainThread, started 4545691072)>, <_DummyThread(Dummy-1, started daemon 123145384022016)>]
Note, that we had to add time.sleep() to give the dummy thread some
time so that it finished before active_count()
and enumerate() calls. This shows another important
property of dummy threads – they lack many facilities thread created with the
threading module have, e.g. we can’t join them.