Skip to content

mypy bug with try/except conditional imports #1153

Description

@timabbott
try:
    import simplejson
except ImportError:
    import json as simplejson

resulst in the error error: Name 'simplejson' already defined

Activity

  1. refi64 commented on Jan 25, 2016

    @refi64
    Contributor

    Pretty sure this is a dup, but I can't find the issue.

  2. refi64 commented on Jan 25, 2016

    @refi64
    Contributor

    Related to #649.

  3. gvanrossum commented on Jan 25, 2016

    @gvanrossum
    Member

    Note that #649 was closed; a buch of "leftover" bugs were opened in its
    place, but I don't see one that matches this pattern, so I think it's a new
    case.

    On Mon, Jan 25, 2016 at 3:19 PM, Ryan Gonzalez notifications@github.com
    wrote:

    Related to #649 #649.

    —
    Reply to this email directly or view it on GitHub
    #1153 (comment).

    --Guido van Rossum (python.org/~guido)

  4. gvanrossum commented on Jan 30, 2016

    @gvanrossum
    Member

    Closed by mistake.

  5. added this to the milestone on Mar 1, 2016
  6. JukkaL commented on Oct 14, 2016

    @JukkaL
    Collaborator

    Another example from #2251 (reported by @RitwikGupta):

    try:
        # Python 3
        from urllib.request import urlopen
    except ImportError:
        # Python 2
        from urllib2 import urlopen
  7. gvanrossum commented on Oct 14, 2016

    @gvanrossum
    Member

    And another from #2253:

    This python code generates an error. It's a common idiom and it would be good if mypy could check for it in some way.

    try:
        import cPickle as pickle
    except ImportError:
        import pickle
    $ mypy --py2 --silent-imports bad.py
    bad.py:4: error: Name 'pickle' already defined
    
  8. JukkaL commented on Oct 14, 2016

    @JukkaL
    Collaborator

    The current workaround is to add a # type: ignore comment. For example:

    try:
        import cPickle as pickle
    except ImportError:
        import pickle  # type: ignore     # <<-- add this
  9. posita commented on Jan 25, 2017

    @posita
    Contributor

    FYI, this doesn't appear to work with sub-modules:

    # This will error
    try:
        import foo.bar
    except ImportError:
        foo = None  # type:ignore

    This seems to work though:

    # This will pass
    try:
        import doesnt.exist  # type:ignore
    except ImportError:
        doesnt = None
    
    # So will this
    try:
        import collections.abc  # type:ignore
    except ImportError:
        collections = None
    
    assert doesnt is None
    assert collections is not None
  10. removed this from the milestone on Mar 29, 2017
  11. quodlibetor commented on Oct 12, 2017

    @quodlibetor
    Contributor

    This is particularly difficult when the import that's happening is a typing import.

    For example, this works:

    $ mypy --version
    mypy 0.530
    
    $ cat no_try.py
    from typing import Dict, Any
    
    JSON = Dict[str, Any]
    
    def accept(obj: JSON) -> Any:
        return obj.pop('hello')
    
    $ mypy --ignore-missing-imports no_try.py
    $ cat with_try.py
    try:
        from typing import Dict, Any
    except:
        from backports.typing import Dict, Any  # type: ignore
    
    JSON = Dict[str, Any]
    
    def accept(obj: JSON) -> Any:
        return obj.pop('hello')
    
    $ mypy --ignore-missing-imports with_try.py
    with_try.py:10: error: Invalid type "with_try.JSON"
    with_try.py:11: error: JSON? has no attribute "pop"
    

    This program should typecheck.

  12. 45 remaining items

  13. cal-pratt commented on Oct 13, 2021

    @cal-pratt

    A pattern that might be nicer for some?

    if TYPE_CHECKING or sys.version_info < (3, 8, 0):
        from typing_extensions import Literal
    else:
        from typing import Literal
  14. added a commit that references this issue on Oct 31, 2021
  15. added a commit that references this issue on Mar 11, 2022
  16. adam-grant-hendry commented on Jun 27, 2022

    @adam-grant-hendry

    Building on an answer from @cjerdonek, would this be an acceptable workaround instead of # type: ignore?:

    try:
        from py3_pkg import module as _module
    except:
        from py2_pkg import module
    else:
        module = _module
  17. atrigent commented on Aug 7, 2022

    @atrigent

    Is this going to be fixed anytime soon?

  18. hauntsaninja commented on Aug 7, 2022

    @hauntsaninja
    Collaborator

    No, it's not, and it's not clear that it should.

    A majority of cases I've seen here are to work around Python stdlib changes, especially Python 2 to Python 3 stuff. sys.version_info checks are the preferred way to do this. Also Python 2 is dead.

    if sys.version_info >= (3, 8):
        import importlib.metadata as importlib_metadata
    else:
        import importlib_metadata
    

    For the remaining cases, it's often not clear that it's sound, especially given nominal typing. Even if the API is structurally the same, nominal isinstance checks could result in surprising behaviour from mypy.

    The only thing we should do in this space is #5018 where you can explicitly define exactly the structure you want with a Protocol, and mypy will confirm.

    For all other cases, if you want to lie to the typechecker, please, go ahead and lie to the type checker (or type ignore):

    if TYPE_CHECKING:
        import json
    else:
        try:
            import simplejson as json
        except ImportError:
            import json
    
  19. added a commit that references this issue on Aug 23, 2022
  20. added a commit that references this issue on May 9, 2023
  21. lilydjwg commented on May 9, 2023

    @lilydjwg

    FYI "type ignore" doesn't work well because in some cases it will cause Unused "type: ignore" comment errors elsewhere (e.g. GitHub Actions).

  22. cebtenzzre commented on May 9, 2023

    @cebtenzzre

    @lilydjwg Issue #8823 was fixed last week and covers what you just described - unused-ignore errors in unreachable code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions