【问题标题】:Changes in import statement python3Changes in import statement python3
【发布时间】:2022-12-01 15:52:51
【问题描述】:

I don't understand the following from pep-0404

In Python 3, implicit relative imports within packages are no longer available - only absolute imports and explicit relative imports are supported. In addition, star imports (e.g. from x import *) are only permitted in module level code.

What is a relative import? In what other places star import was allowed in python2? Please explain with examples.

【问题讨论】:

    标签: python python-3.x


    【解决方案1】:

    Relative import happens whenever you are importing a package relative to the current script/package.

    Consider the following tree for example:

    mypkg
    ├── base.py
    └── derived.py
    

    Now, your derived.py requires something from base.py. In Python 2, you could do it like this (in derived.py):

    from base import BaseThing
    

    Python 3 no longer supports that since it's not explicit whether you want the 'relative' or 'absolute' base. In other words, if there was a Python package named base installed in the system, you'd get the wrong one.

    Instead it requires you to useexplicit importswhich explicitly specify location of a module on a path-alike basis. Your derived.py would look like:

    from .base import BaseThing
    

    The leading . says 'import base from module directory'; in other words, .base maps to ./base.py.

    Similarly, there is .. prefix which goes up the directory hierarchy like ../ (with ..mod mapping to ../mod.py), and then ... which goes two levels up (../../mod.py) and so on.

    Please however note that the relative paths listed above were relative to directory where current module (derived.py) resides in,notthe current working directory.


    @BrenBarnhas already explained the star import case. For completeness, I will have to say the same ;).

    For example, you need to use a few math functions but you use them only in a single function. In Python 2 you were permitted to be semi-lazy:

    def sin_degrees(x):
        from math import *
        return sin(degrees(x))
    

    Note that it already triggers a warning in Python 2:

    a.py:1: SyntaxWarning: import * only allowed at module level
      def sin_degrees(x):
    

    In modern Python 2 code you should and in Python 3 you have to do either:

    def sin_degrees(x):
        from math import sin, degrees
        return sin(degrees(x))
    

    or:

    from math import *
    
    def sin_degrees(x):
        return sin(degrees(x))
    

    【讨论】:

    • This of course fails when one runs python derived.py
    • @MiloBem yep, so what do you do if you need both cases to work?
    • Following this paradigm just results in an import error. My IDE can see what I'm trying to do based on autocomplete working correctly, but Python doesn't care for it.
    【解决方案2】:

    For relative imports see the documentation. A relative import is when you import from a module relative to that module's location, instead of absolutely from sys.path.

    As for import *, Python 2 allowed star imports within functions, for instance:

    >>> def f():
    ...     from math import *
    ...     print sqrt
    

    A warning is issued for this in Python 2 (at least recent versions). In Python 3 it is no longer allowed and you can only do star imports at the top level of a module (not inside functions or classes).

    【讨论】:

    • Why was that decision made?
    • My guess is that idea behind it is 'Explicit is better than implicit.' from PEP20 - The Zen of Python. Dot before module makes relative/nonrelative linking explicit thus resolving possible name collisions. Although 'Readability counts.' suffers slightly.
    • No, in fact it was the "opposite", "practicality beats purity" decision. That was necessary in order to optimize local variable access inside functions, since without "import *", compiler always knows just by analyzing the code, what variables are local and can be looked up directly. In fact, functions don't even use a dict for local storage, but an optimized array where variables get unique indices.
    【解决方案3】:

    To support both Python 2 and Python 3, use explicit relative imports as below. They are relative to the current module. They have been supported starting from 2.5.

    from .sister import foo
    from . import brother
    from ..aunt import bar
    from .. import uncle
    

    【讨论】:

    • import .brother gives me an invalid syntax error in Python 3.5. This is normal? I haveinit.py in the directory it is in
    • import .brother is invalid syntax for both python 2 and 3
    • @RodrigoE.Principe and so seems to be import ..uncle. Fixed. Oh, what have I been thinking... probably got distracted by the knights who say Ni!
    【解决方案4】:

    Added another case to Michał Górny's answer:

    Note that relative imports are based on the name of the current module. Since the name of the main module is always "__main__", modules intended for use as the main module of a Python application must always use absolute imports.

    【讨论】:

      猜你喜欢
      • 2016-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-05
      • 1970-01-01
      • 2022-12-26
      • 2020-03-26
      • 1970-01-01
      相关资源
      最近更新 更多