pythonpython-3.xmodulepython-module

Python Pylance unresolved import from class exposed by __init__.py


Issue

I'm working on updating an Python library to use modern versions of Python (the Equation library) and am having trouble with Pylance when importing from the module. The base form of the library also had this issue, but for reference, here's my fork: Antyos/Equation.

As the library describes, you are supposed to be able to import the Expression class like so:

from Equation import Expression

e = Expression("sin(x+y^2)")

This code works, however, Pylance will give the following error:

"Expression" is unknown import symbol Pylance(reportGeneralTypeIssues)

If I import the code as follows, I don't receive the error and I can get type hints.

from Equation.core import Expression

My Understanding

I roughly understand the issue--as shown in the file structure below, it makes sense that from Equation.core import Expression would work. I also understand that __init__.py is exposing the Expression class to the top level of the module. (I still don't totally get how this part works and I can't seem to find the right page/section detailing it.)

Equation
├─ __init__.py
├─ _info.py
├─ core.py  # Contains Expression()
├─ equation_base.py
├─ equation_scipy.py
├─ similar.py
└─ util.py

While I'm pretty sure I could get around this issue by writing a stub (*.pyi) file, it seems redundant (to me) to create a stub file for a class that I already have direct access to; why would I need to redefine something that's already there? However, it is also likely that I don't completely understand how stub files / module imports work and this is the right way.

I'm sure this issue has been addressed before, but I think I've been using the wrong terminology. What am I missing?


Solution

  • In __init__.py I believe you are performing relative import:

    try:
        from Equation.core import Expression
    except ImportError:
        from core import Expression
    

    The correct way to perform relative import here is to put . in front of core like this .core.

    For example:

    try:
        from Equation.core import Expression
    except ImportError:
        from .core import Expression
    

    This fixes Pylance when I tried it.

    Spec reference: https://docs.python.org/3/reference/import.html#package-relative-imports