Python `from module import name` vs `import module`

Viewed 1591

Why this doesn't work:

>>> import structlog
>>> structlog.contextvars.bind_contextvars()
AttributeError: module 'structlog' has no attribute 'contextvars'
>>>

But this does:

>>> from structlog.contextvars import bind_contextvars
>>> bind_contextvars()
>>>

Can't seem to find documentation on when to use from x import y vs import x.

2 Answers

I am wondering which version of the library and Python you are using because with Python 3.8 (Win 10 x64) and structlog 21.1.0 (newest available) I am not seeing the error and as the code indicates (__init__.py of the package), the sub-modules are imported (because contextvars.py exists):

try:
    from structlog import contextvars
except ImportError:
    contextvars = None  # type: ignore

In some older version it could be different and the sub-module could have been imported only in some situations which would cause the errors when not.

While I was unable to replicate this issue in a separate environment...

~/GivingCaringSolution$ python
Python 3.8.9 (default, May  3 2021, 02:40:41) 
[GCC 7.5.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import structlog
>>> structlog.contextvars.bind_contextvars()
>>> 

...the general answer is that this behavior depends on how a specific library was constructed and whether or not all sub-modules (or the sub-modules you are trying to use, at any rate) such as contextvars are resolved and added as members of the imported module (such as structlog) at the time that the main module is imported.

The documentation to follow for practical usage here is the official documentation provided by the maintainers of a given module, if any. Its quality, and the amount of guidance on how to import, will naturally vary by author and by module.

In this particular case, the official structlog documentation about its context variables module would be a great place to start.

Related