Why use `from module import A as A` instead of just `from module import A`

Question:

When reading source code of fastapi, this line make me fuzzy:

from starlette.testclient import TestClient as TestClient

Why not just: from starlette.testclient import TestClient?

Asked By: Waket Zheng

||

Answers:

From the point of view of executable code, there is absolutely no difference in terms of the Python bytecode being generated by the two different code examples (using Python 3.9):

>>> dis.dis('from starlette.testclient import TestClient as TestClient')
  1           0 LOAD_CONST               0 (0)
              2 LOAD_CONST               1 (('TestClient',))
              4 IMPORT_NAME              0 (starlette.testclient)
              6 IMPORT_FROM              1 (TestClient)
              8 STORE_NAME               1 (TestClient)
             10 POP_TOP
             12 LOAD_CONST               2 (None)
             14 RETURN_VALUE
>>> dis.dis('from starlette.testclient import TestClient')
  1           0 LOAD_CONST               0 (0)
              2 LOAD_CONST               1 (('TestClient',))
              4 IMPORT_NAME              0 (starlette.testclient)
              6 IMPORT_FROM              1 (TestClient)
              8 STORE_NAME               1 (TestClient)
             10 POP_TOP
             12 LOAD_CONST               2 (None)
             14 RETURN_VALUE

As shown, they are exactly identical. (Related thread and thread.)

However, the comment by Graham501617 noted how modern type hinting validators (such as mypy) accept this particular syntax to denote the re-export of that imported name (the other being the __all__, which thankfully they did end up correctly supporting as that has been a standard syntax to denote symbols to (re-)export since Python 2). Specifically, as per the description of Stub Files in the referenced PEP 0484, quote:

  • Modules and variables imported into the stub are not considered exported from the stub unless the import uses the import ... as ... form or the equivalent from ... import ... as ... form. (UPDATE: To clarify, the intention here is that only names imported using the form X as X will be exported, i.e. the name before and after as must be the same.)

Which means the library is likely following that particular convention to facilitate the re-export of the TestClient name from the stub (module) file that was referenced in the question. As a matter of fact, looking at git blame for the relevant file in the packages pointed to this commit (direct link to relevant diff for the file) which referenced this issue, which contains a similar brief discussion to address the exact type hinting issue; this was done to ensure mypy will treat those imported names as re-export, thus allowing the usage of the --no-implicit-reexport flag (which --strict has likely implicitly enabled).

Answered By: metatoaster
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.