Type hinting may cause cyclic imports
Recently I was working on rss3 SDK. In order to facilitate development, I just make a python version of the reference JavaScript SDK, which means the usage should be pretty similar between both.
Make a Python version
What’s more, to make a clear code,I use type hinting in the new project. However, there is a code snippet in JavaScript version:
1 | # index.ts |
Yes, the two files refer to each other. Actually, it happens on many other files. When I turned this into Python version:
1 | # index.py |
circular import
It didn’t seem any errors, but when I started testing the problems appeared.
1 | E ImportError: cannot import name 'RSS3' from partially initialized module 'rss3.src.index' (most likely due to a circular import) |
how to solve this problem ? Don’t worry, PEP 484 has given a solution.
Solutions
When a type hint contains names that have not been defined yet, that definition may be expressed as a string literal, to be resolved later.
So we can modify our code like the following:
1 | class File: |
That’s okay already.
Sometimes there’s code that must be seen by a type checker (or other static analysis tools) but should not be executed. For such situations the typing module defines a constant, TYPE_CHECKING, that is considered True during type checking (or other static analysis) but False at runtime.
Modify out code again:
1 | if TYPE_CHECKING: |
What’s more
if we are using Python 3.7+, we can at least skip having to provide an explicit string annotation by taking advantage of PEP 563:
1 | from __future__ import annotations |
The from __future__ import annotations
import will make all type hints be strings and skip evaluating them.