line34
Coding, Scripting, Administration

Lost in namespace

I ran into the problem that I wanted to import a global module of the same name as the current module, and it was throwing an error.

In my little time tracking helper tool octodon I ran into the problem that I wanted to import a global module of the same name as the current module, and it was throwing an error. I had this in octodon/jira.py:

from __future__ import absolute_import
from jira import JIRA
from jira import JIRAError

which got me the error

$ bin/python src/octodon/tests.py
[...]
ImportError: cannot import name 'JIRA' from 'jira' ([...]/src/octodon/jira.py)

It was obviously trying to import JIRA from octodon.jira, not from the global jira package that I wanted to use. I was running Python 3, but even on Python 2 the absolute_import should make sure this works. I straightened out the namespace declarations, but still no luck.

Then I realized two things:

When running bin/python src/octodon/tests.py, my sys.path looked like this:

(Pdb) sys.path
['[...]/src/octodon',
'/nix/store/z4y3q5nsm1hhk7g18ywpnsdgqcgsvc2i-python3-3.7.6/lib/python37.zip',
'/nix/store/z4y3q5nsm1hhk7g18ywpnsdgqcgsvc2i-python3-3.7.6/lib/python3.7',
'/nix/store/z4y3q5nsm1hhk7g18ywpnsdgqcgsvc2i-python3-3.7.6/lib/python3.7/lib-dynload',
'[...]/lib/python3.7/site-packages',
'[...]/src']

But when running bin/octodon it looked like this instead:

(Pdb++) sys.path
['[...]/bin',
'/nix/store/z4y3q5nsm1hhk7g18ywpnsdgqcgsvc2i-python3-3.7.6/lib/python37.zip',
'/nix/store/z4y3q5nsm1hhk7g18ywpnsdgqcgsvc2i-python3-3.7.6/lib/python3.7',
'/nix/store/z4y3q5nsm1hhk7g18ywpnsdgqcgsvc2i-python3-3.7.6/lib/python3.7/lib-dynload',
'[...]/lib/python3.7/site-packages',
'[...]/src']

In the first case, the first entry was the directory that contained tests.py, while in the second case it was the bin directory that I was calling the application from. This reminded me of what I had read in a stackoverflow post titled What does from __future__ import absolute_import actually do?: When calling code by path (src/octodon/tests.py) the directory containing the file will be added to the path, but when running it as a module (-m octodon.tests) the current directory will be added instead. bin/octodon was generated from an entry-point and was doing it in the second way, which worked, but my call to run the tests did it the first way, which always searched src/octodon for the jira module first, shadowing the global one.

So, when running bin/python -m octodon.tests instead, it was suddenly working fine:

$ bin/python -m octodon.tests
[...]
OK (skipped=1)
26th May 2020Filed under: python   namespace   path