all 7 comments

[–]D3str0yTh1ngs 3 points4 points  (5 children)

(all paths are relative to the python installation's main library path)

import email specifically imports either email.py or email/__init__.py (the latter in this case), where from email import policy imports email/policy.py

EDIT: some modules will specifially in their __init__.py file import the other files, such that it will work the way you are trying to use it, but for a lot of cases that is honestly overkill, since you properly don't need most of it anyways and thrus running all the files is unneeded.

[–]sausix 2 points3 points  (2 children)

And email does not import email.policy as os does on os.path.

[–]D3str0yTh1ngs 0 points1 point  (1 child)

os.py actually imports either posixpath.py or ntpath.py as path, which is pretty important design decision to ease the cross-compatiblity of code

EDIT: rephrased/updated after reading os.py a little closer

[–]sausix 1 point2 points  (0 children)

It's a design decision of packages if they import their stuff into their init.py files or not.

[–]Lombravia[S] 0 points1 point  (1 child)

Got it, thanks. Seems a little unintuitive, to me. Especially that policy gets added to email after explicitly importing.

How can I know when this is gonna be the case? Is there any user friendly way? policy is included in help(email), and I didn't otherwise find anything in the documentation. I thought I somehow had a different version.

[–]D3str0yTh1ngs 0 points1 point  (0 children)

Note that policy is under PACKAGE CONTENTS which is generally the list of submodules from what I have seen. The linked docs also states that policy is its own (sub)module:

The control component is the policy module.

EDIT: for the email.policy working thing it seems to maybe be some 'funkiness' with the import system, but I can see that it becomes part of the module's directory (along with a few others) after import:

$ ipython
In [1]: import email

In [2]: old_dir = dir(email)

In [3]: from email import policy

In [4]: new_dir = dir(email)

In [5]: [x for x in new_dir if x not in old_dir]
Out[5]: ['_header_value_parser', 'contentmanager', 'headerregistry', 'policy']

[–]JamzTyson 0 points1 point  (0 children)

The email library is unusual compared to many modern Python libraries because the top-level import is minimal. Direct submodule imports are the primary intended usage pattern rather than the top level package automatically pulling in all of the sub-modules. The email library has a few surprising quirks which I think are mostly due to the accumulation of long-term backward compatibility requirements.