# Module 'importlib' has no attribute 'metadata'

**URL:** <https://discuss.python.org/t/module-importlib-has-no-attribute-metadata/20947>\
**Category:** Packaging\
**Created:** [November 10, 2022, 9:59pm UTC](https://discuss.python.org/t/module-importlib-has-no-attribute-metadata/20947 "2022-11-10T21:59:41Z")\
**Posts on this page:** 18\
**Page:** 1

<div class="post-metadata">

**Author:** ![bryevdv](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/bryevdv/32/7424_2.png) [@bryevdv](https://discuss.python.org/u/bryevdv)\
**Post date:** [November 10, 2022, 9:59pm UTC](https://discuss.python.org/t/module-importlib-has-no-attribute-metadata/20947/1 "2022-11-10T21:59:41Z")

</div>

Can someone explain what can cause this?

I have run into a situation where:

```python
import importlib.metadata 
importlib.metadata # Error!

```

But:

```python
import importlib.metadata as importlib_metadata
importlib_metadata # NO error!

```

I have seen other similar odd issues with this module. What is going on? I can provide more details if necessary, it would just be a bit of a slog to write up. Mostly I’m hoping that to zeroth order someone can just shed light about any special assumptions this module has, or under what circumstances the `metadata` submodule would just _not exist_.

Edit: Python 3.10 FYI

---

<div class="post-metadata">

**Author:** ![saaketp](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/saaketp/32/6703_2.png) [@saaketp](https://discuss.python.org/u/saaketp)\
**Post date:** [November 10, 2022, 10:21pm UTC](https://discuss.python.org/t/module-importlib-has-no-attribute-metadata/20947/2 "2022-11-10T22:21:52Z")

</div>

Are you sure you did

```python
import importlib.metadata

```

and not

```python
import importlib

```

Most of the time I have seen people run into that is when they do the latter and then try to use `importlib.metadata`. But if you only import `importlib` you don’t get `importlib.metadata`, you have to import the submodule explicitly.

---

<div class="post-metadata">

**Author:** ![bryevdv](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/bryevdv/32/7424_2.png) [@bryevdv](https://discuss.python.org/u/bryevdv)\
**Post date:** [November 10, 2022, 10:23pm UTC](https://discuss.python.org/t/module-importlib-has-no-attribute-metadata/20947/3 "2022-11-10T22:23:16Z")

</div>

@saaketp Yes, 100% sure, which is why I am _very_ confused.

Edit:

```auto
bk301-py10 ❯ bokeh serve --show foo.py
2022-11-10 14:23:59,567 Starting Bokeh server version 3.0.1 (running on Tornado 6.2)
2022-11-10 14:23:59,900 User authentication hooks NOT provided (default user enabled)
2022-11-10 14:23:59,903 Bokeh app running at: http://localhost:5006/foo
2022-11-10 14:23:59,903 Starting Bokeh server with process id: 30450
> /Users/bryan/tmp/foo.py(28)<module>()
-> import pyproj
(Pdb) import importlib.metadata
(Pdb) importlib.metadata
*** AttributeError: module 'importlib' has no attribute 'metadata'
(Pdb)

```

FWIW Bokeh server is in the unusual position of being a Python application that runs other Python applications, which sometimes introduces weirdness. I can believe there is something we might need to change or start doing on our end to make things more “normal” for the app code, but I also don’t know what that might be.

---

<div class="post-metadata">

**Author:** ![btskinn](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/btskinn/32/835_2.png) [@btskinn](https://discuss.python.org/u/btskinn)\
**Post date:** [November 10, 2022, 10:30pm UTC](https://discuss.python.org/t/module-importlib-has-no-attribute-metadata/20947/4 "2022-11-10T22:30:57Z")

</div>

I _cannot_ reproduce this on my Windows Store install of Python 3.10:

```auto
C:\>python3.10
Python 3.10.8 (tags/v3.10.8:aaaf517, Oct 11 2022, 16:50:30) [MSC v.1933 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import importlib.metadata
>>> importlib.metadata
<module 'importlib.metadata' from 'C:\\Program Files\\WindowsApps\\PythonSoftwareFoundation.Python.3.10_3.10.2288.0_x64 __qbz5n2kfra8p0\\lib\\importlib\\metadata\\__ init__.py'>

```

Is it possible that Bokeh server is invoking a different interpreter version than the 3.10 you think it is?

What’s the output of `import sys; sys.version_info` in that same context?

---

<div class="post-metadata">

**Author:** ![bryevdv](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/bryevdv/32/7424_2.png) [@bryevdv](https://discuss.python.org/u/bryevdv)\
**Post date:** [November 10, 2022, 10:33pm UTC](https://discuss.python.org/t/module-importlib-has-no-attribute-metadata/20947/5 "2022-11-10T22:33:51Z")

</div>

No, the Bokeh server runs the app code in-process (no subprocess invocation), so it’s the same:

```auto
(Pdb) import sys
(Pdb) sys.version
'3.10.6 (main, Oct 24 2022, 11:04:34) [Clang 12.0.0]'

```

---

<div class="post-metadata">

**Author:** ![pradyunsg](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/pradyunsg/32/206_2.png) [@pradyunsg](https://discuss.python.org/u/pradyunsg)\
**Post date:** [November 10, 2022, 10:37pm UTC](https://discuss.python.org/t/module-importlib-has-no-attribute-metadata/20947/6 "2022-11-10T22:37:39Z")

</div>

What is the repr of importlib, and sys.modules, and sys.path?

---

<div class="post-metadata">

**Author:** ![steve.dower](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/steve.dower/32/56_2.png) [@steve.dower](https://discuss.python.org/u/steve.dower)\
**Post date:** [November 10, 2022, 10:38pm UTC](https://discuss.python.org/t/module-importlib-has-no-attribute-metadata/20947/7 "2022-11-10T22:38:47Z")

</div>

Anyone likely to be doing reloads or messing with `sys.modules`?

Often the second import of a module can do weird things like this, though there shouldn’t be a second import because it should be cached. But then, people like to try and “clear the cache,” which is much harder than `del sys.modules[name]`…

---

<div class="post-metadata">

**Author:** ![bryevdv](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/bryevdv/32/7424_2.png) [@bryevdv](https://discuss.python.org/u/bryevdv)\
**Post date:** [November 10, 2022, 10:43pm UTC](https://discuss.python.org/t/module-importlib-has-no-attribute-metadata/20947/8 "2022-11-10T22:43:47Z")

</div>

> What’s the output of import sys; sys.version\_info in that same context?

short ones:

```auto
(Pdb) importlib
<module 'importlib' from '/Users/bryan/anaconda/envs/bk301-py10/lib/python3.10/importlib/ __init__.py'>
(Pdb) sys.path
['/Users/bryan/tmp', '/Users/bryan/anaconda/envs/bk301-py10/bin', '/Users/bryan/anaconda/envs/bk301-py10/lib/python310.zip', '/Users/bryan/anaconda/envs/bk301-py10/lib/python3.10', '/Users/bryan/anaconda/envs/bk301-py10/lib/python3.10/lib-dynload', '/Users/bryan/anaconda/envs/bk301-py10/lib/python3.10/site-packages', '/Users/bryan/anaconda/envs/bk301-py10/lib/python3.10/site-packages/GDAL-3.4.1-py3.10-macosx-10.9-x86_64.egg']

```

`sys.modules` is big, has to go in a gist: [https://gist.github.com/bryevdv/239251d5ea93da3dd63b93ee0671218a](https://gist.github.com/bryevdv/239251d5ea93da3dd63b93ee0671218a)

---

<div class="post-metadata">

**Author:** ![bryevdv](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/bryevdv/32/7424_2.png) [@bryevdv](https://discuss.python.org/u/bryevdv)\
**Post date:** [November 10, 2022, 10:45pm UTC](https://discuss.python.org/t/module-importlib-has-no-attribute-metadata/20947/9 "2022-11-10T22:45:44Z")

</div>

@steve.dower Sort of, Bokeh programmatically creates a module for the app code to be executed in for each session, then installs that module in `sys.modules`. But nothing is deleting modules at the point this error happens. \[1\] This has all worked fine for many years but it seems like some recent developments mean we need to update some aspect of how this is handed.

Edit: @steve.dower oh wait, do you mean this:

> <https://github.com/bokeh/bokeh/blob/5204d0ee6d87c66d416a021e0a34389c20dd31b5/src/bokeh/ __init__.py#L85>

We could stop doing that…

* * *

1. and we only clean up the modules we, ourselves, installed, some time after a session ends.

---

<div class="post-metadata">

**Author:** ![saaketp](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/saaketp/32/6703_2.png) [@saaketp](https://discuss.python.org/u/saaketp)\
**Post date:** [November 10, 2022, 10:55pm UTC](https://discuss.python.org/t/module-importlib-has-no-attribute-metadata/20947/10 "2022-11-10T22:55:26Z")

</div>

Can you try

```python
import sys
print("importlib" in sys.modules and hasattr(sys.modules["importlib"], "metadata"))
print("importlib.metadata" in sys.modules)

```

Also possibly related  
[https://mail.python.org/archives/list/python-dev@python.org/thread/VIPXZRK3OJNSVNSZSAJ7CO6QFC2RX27W/](https://mail.python.org/archives/list/python-dev@python.org/thread/VIPXZRK3OJNSVNSZSAJ7CO6QFC2RX27W/)

---

<div class="post-metadata">

**Author:** ![bryevdv](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/bryevdv/32/7424_2.png) [@bryevdv](https://discuss.python.org/u/bryevdv)\
**Post date:** [November 10, 2022, 11:01pm UTC](https://discuss.python.org/t/module-importlib-has-no-attribute-metadata/20947/11 "2022-11-10T23:01:52Z")

</div>

@saaketp

```auto
bk301-py10 ❯ bokeh serve --show foo.py
2022-11-10 15:01:01,348 Starting Bokeh server version 3.0.1 (running on Tornado 6.2)
2022-11-10 15:01:01,574 User authentication hooks NOT provided (default user enabled)
2022-11-10 15:01:01,577 Bokeh app running at: http://localhost:5006/foo
2022-11-10 15:01:01,577 Starting Bokeh server with process id: 30849
BokehDeprecationWarning: tile_providers module was deprecated in Bokeh 3.0.0 and will be removed, use add_tile directly instead.
> /Users/bryan/tmp/foo.py(28)<module>()
-> import pyproj
(Pdb) import sys
(Pdb) print("importlib" in sys.modules and hasattr(sys.modules["importlib"], "metadata"))
False
(Pdb) print("importlib.metadata" in sys.modules)
True
(Pdb)

```

---

<div class="post-metadata">

**Author:** ![bryevdv](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/bryevdv/32/7424_2.png) [@bryevdv](https://discuss.python.org/u/bryevdv)\
**Post date:** [November 10, 2022, 11:03pm UTC](https://discuss.python.org/t/module-importlib-has-no-attribute-metadata/20947/12 "2022-11-10T23:03:47Z")

</div>

@saaketp @pradyunsg @steve.dower

It seems that removing the `del importlib.metadata` in the `bokeh/ __init__.py` module might fix:

```auto
(Pdb) import importlib.metadata
(Pdb) importlib.metadata
<module 'importlib.metadata' from '/Users/bryan/anaconda/envs/bk301-py10/lib/python3.10/importlib/metadata/ __init__.py'>
(Pdb)

```

---

<div class="post-metadata">

**Author:** ![saaketp](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/saaketp/32/6703_2.png) [@saaketp](https://discuss.python.org/u/saaketp)\
**Post date:** [November 10, 2022, 11:05pm UTC](https://discuss.python.org/t/module-importlib-has-no-attribute-metadata/20947/13 "2022-11-10T23:05:28Z")

</div>

Okay then seems like the exact same problem as that mailing list post.  
If `importlib.metadata` is already in sys.modules then `import importlib.metadata` does nothing, so importlib doesn’t get the metadata attribute. It should have got the attribute set when you imported the first time, but then that `del` statement deleted it.

---

<div class="post-metadata">

**Author:** ![bryevdv](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/bryevdv/32/7424_2.png) [@bryevdv](https://discuss.python.org/u/bryevdv)\
**Post date:** [November 10, 2022, 11:09pm UTC](https://discuss.python.org/t/module-importlib-has-no-attribute-metadata/20947/14 "2022-11-10T23:09:21Z")

</div>

Just to be clear (for my understanding), the `metadata` attribute (submodule?) is created dynamically by `importlib` import, but if it is deleted, then subsequent, explicit `import importlib.metadata` does not re-create it, because `importlib` is still cached in `sys.modules`?

That seems understandable in hindsight, but if I am honest, also seems like a foot-gun. 🙂

---

<div class="post-metadata">

**Author:** ![bryevdv](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/bryevdv/32/7424_2.png) [@bryevdv](https://discuss.python.org/u/bryevdv)\
**Post date:** [November 10, 2022, 11:33pm UTC](https://discuss.python.org/t/module-importlib-has-no-attribute-metadata/20947/15 "2022-11-10T23:33:12Z")

</div>

Well, actually I guess this is just Python 101 and I am just over way overthinking things. I really almost never, ever do `import foo.bar` without aliasing (or importing `from`).

---

<div class="post-metadata">

**Author:** ![brettcannon](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/brettcannon/32/34895_2.png) [@brettcannon](https://discuss.python.org/u/brettcannon)\
**Post date:** [November 10, 2022, 11:34pm UTC](https://discuss.python.org/t/module-importlib-has-no-attribute-metadata/20947/16 "2022-11-10T23:34:00Z")

</div>

> [@bryevdv](#):
>
> the `metadata` attribute (submodule?) is created dynamically by `importlib` import

When you try to import a submodule, if it succeeds it gets added to `sys.modules` and then set as an attribute on the parent package (that’s how the attribute access in your own code works). If the import fails, the name gets set to `None` in `sys.modules` to avoid trying a known-bad import again. Then future imports pull from `sys.modules`.

You can follow the code starting at [cpython/Lib/importlib/\_bootstrap.py at 3a1dde8f29215418ec4e27fd6234cfa19a5407c6 · python/cpython · GitHub](https://github.com/python/cpython/blob/3a1dde8f29215418ec4e27fd6234cfa19a5407c6/Lib/importlib/_bootstrap.py#L1242) as to how this all works.

---

<div class="post-metadata">

**Author:** ![bryevdv](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/bryevdv/32/7424_2.png) [@bryevdv](https://discuss.python.org/u/bryevdv)\
**Post date:** [November 11, 2022, 1:01am UTC](https://discuss.python.org/t/module-importlib-has-no-attribute-metadata/20947/17 "2022-11-11T01:01:19Z")

</div>

@brettcannon Sure, all of that makes sense. I guess what surprised me here is the mode of failure. If I do `del foo.bar`, and then subsequently do `import foo.bar` I guess I would have expected that to fail immediately, rather than silently “work” (if it is not going to be automagic’ed to “actually work”). Like I said I almost always “import as” or “import from” so my intuition just got caught off guard.

---

<div class="post-metadata">

**Author:** ![steve.dower](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/steve.dower/32/56_2.png) [@steve.dower](https://discuss.python.org/u/steve.dower)\
**Post date:** [November 11, 2022, 10:29am UTC](https://discuss.python.org/t/module-importlib-has-no-attribute-metadata/20947/18 "2022-11-11T10:29:36Z")

</div>

The trick here is that `del foo.bar` isn’t doing anything with modules.

It translates into (approx) `foo. __delattr__ (bar)`. So all you’re doing is removing the attribute from `foo`, but `foo.bar` is still imported just as it ever was.
