Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What causes an ImportError to report "(unknown location)"?

Looking at this question, there is this import error:

>>> from flask_security import login_user
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: cannot import name 'login_user' from 'flask_security' (unknown location)

What causes the "(unknown location)" message?

Prior to seeing this, I had a kind of vague assumption that it meant the module was built in to python itself, like sys, and so it did not have any external file at all.

But that is clearly not the case in the linked question.

like image 691
John Gordon Avatar asked Oct 30 '25 06:10

John Gordon


1 Answers

(unknown location) appears in an ImportError whenever the module's __file__ attribute is not set (or is set to something other than a string).

This can be the case for a variety of reasons:

  1. C modules that are statically1 linked to the Python interpreter leave __file__ unset. This includes modules like sys as mentioned in the question.
  2. For modules representing namespace packages, __file__ will be set to None.
  3. If the module was created using types.ModuleType, __file__ won't be set.
  4. When a module is imported using a custom loader from importlib, whether __file__ is set depends on the implementation of the loader.

1Dynamically loaded extension modules will set __file__ to the path of the shared library.

The following produces an (unknown location) import error by directly creating a module with types.ModuleType. Note that we can set the module's __file__ attribute at any point to change how the error message is displayed.

import sys
import types

sys.modules["foo"] = types.ModuleType("foo", "Foo module")

# Import with no __file__ set
>>> from foo import bar
Traceback (most recent call last):
...
ImportError: cannot import name 'bar' from 'foo' (unknown location)

# Set __file__ to a dummy value
>>> sys.modules["foo"].__file__ = "/fake/path/to/foo.py"
>>> from foo import bar
Traceback (most recent call last):
...
ImportError: cannot import name 'bar' from 'foo' (/fake/path/to/foo.py)

Similarly, we can see the same (unknown location) behavior when using a custom loader that does not set the module's __file__ attribute:

import importlib.abc

class SimpleLoader(importlib.abc.Loader):
    def create_module(self, spec):
        return None

    def exec_module(self, module):
        pass


loader = SimpleLoader()
loader.load_module("foo")

>>> from foo import bar
Traceback (most recent call last):
...
ImportError: cannot import name 'bar' from 'foo' (unknown location)

If instead the custom loader sets __file__ to some value, we'll set that value instead of (unknown location):

import importlib.abc


class SpoofLoader(importlib.abc.Loader):
    def create_module(self, spec):
        return None

    def exec_module(self, module):
        module.__file__ = "spoofed location"


loader = SpoofLoader()
loader.load_module("foo")

>>> from foo import bar
Traceback (most recent call last):
...
ImportError: cannot import name 'bar' from 'foo' (spoofed location)
like image 169
Brian Avatar answered Nov 01 '25 21:11

Brian



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!