How do I find the version of email I'm using?

I’m using Python 3.11 on Windows 10. I’m still fairly new to Python.

In my main program I’d like to display some version information for some of the modules. I use the email standard package to send email via SMTP but my email sending routine is in another library .py file I created and import into my main program. Here’s what I’ve tried to put in my main program.

import email
# (some more code)
MODULEVER = f"""
---Module versions:
email v{email.__version__}
email.encoders v{email.encoders.__version__}
Pandas v{pandas.__version__}
Psycopg2 (Postgresql interface) v{psycopg2.__version__} https://pypi.org/project/psycopg2/
xlsxwriter v{xlsxwriter.__version__}
"""
print(MODULEVER)

The version shows for the other packages but not for email or email.encoders. The error I get when I run this is “AttributeError: module ‘email’ has no attribute ‘__version__’”. I tried searching Google for a solution with no luck.

  1. Do standard libraries even have a __version__ attribute?
  2. If so, how do I display the version info for email?
  3. Am I misunderstanding something basic about modules?

Thank you!

No, the existence of a __version__ attribute is not prescribed in any way. Even for 3rd party packages it only sometimes exists. For stdlib packages it also doesn’t really make sense since updates of the stdlib are tied to updates of the python version, so you can just use the python version as a proxy.

If you’re concerned about whether the email module is really the one from the Python version that you expect, the easiest way to check would be to look at its __file__ attribute, which tells you the file name that it was loaded from. Any mismatch with your Python version should be obvious from that.

In general, no. That’s because they’re updated in lockstep with the Python version.

A few do, like json, because they were originally third-party and the third-party developer chose to add one. The version number reflects what version was brought in - but AFAIK it doesn’t get updated in any way if there’s separate maintenance by the dev team. (After all, that would be no more truthful.)

There is no special meaning to such an attribute, as far as either Python or the packaging ecosystem are concerned. You can possibly give it meaning by making your build tools check for it and use it. But the authoritative version for third-party packages comes from importlib.metadata.version (or the .version of a pkg_resources.get_distribution result), which uses the PyPI distribution name, not the import name. And the authoritative version for standard library packages doesn’t exist, unless you count the corresponding Python version.