Python中的绝对导入和相对导入

If you’ve worked on a Python project that has more than one file, chances are you’ve had to use an import statement before.

如果您从事的Python项目有多个文件,那么您以前可能不得不使用import语句。

Even for Pythonistas with a couple of projects under their belt, imports can be confusing! You’re probably reading this because you’d like to gain a deeper understanding of imports in Python, particularly absolute and relative imports.

即使对于拥有多个项目的Pythonista使用者,导入也可能会造成混淆! 您可能正在阅读本文,因为您想对Python中的导入(尤其是绝对导入和相对导入)有更深入的了解。

In this tutorial, you’ll learn the differences between the two, as well as their pros and cons. Let’s dive right in!

在本教程中,您将学习两者之间的区别以及它们的优缺点。 让我们潜入吧!

Free Bonus: 5 Thoughts On Python Mastery, a free course for Python developers that shows you the roadmap and the mindset you’ll need to take your Python skills to the next level.

免费奖金: 关于Python精通的5个想法 ,这是针对Python开发人员的免费课程,向您展示了将Python技能提升到新水平所需的路线图和心态。

进口快速回顾 (A Quick Recap on Imports)

You need to have a good understanding of Python modules and packages to know how imports work. A Python module is a file that has a .py extension, and a Python package is any folder that has modules inside it (or, in Python 2, a folder that contains an __init__.py file).

您需要对Python模块和软件包有充分的了解,才能知道导入的工作方式。 Python模块是具有.py扩展名的文件,而Python包是内部具有模块的任何文件夹(或者在Python 2中是包含__init__.py文件的文件夹)。

What happens when you have code in one module that needs to access code in another module or package? You import it!

当一个模块中的代码需要访问另一模块或程序包中的代码时,会发生什么? 您导入它!

导入方式 (How Imports Work)

But how exactly do imports work? Let’s say you import a module abc like so:

但是进口究竟如何工作? 假设您像这样导入模块abc

 import import abc
abc

The first thing Python will do is look up the name abc in sys.modules. This is a cache of all modules that have been previously imported.

Python要做的第一件事是在sys.modules查找名称abc 。 这是先前已导入的所有模块的缓存。

If the name isn’t found in the module cache, Python will proceed to search through a list of built-in modules. These are modules that come pre-installed with Python and can be found in the Python Standard Library. If the name still isn’t found in the built-in modules, Python then searches for it in a list of directories defined by sys.path. This list usually includes the current directory, which is searched first.

如果在模块缓存中找不到该名称,Python将继续搜索内置模块列表。 这些是Python预先安装的模块,可以在Python标准库中找到 。 如果在内置模块中仍找不到该名称,则Python然后在sys.path定义的目录列表中搜索该名称。 该列表通常包括当前目录,该目录首先被搜索。

When Python finds the module, it binds it to a name in the local scope. This means that abc is now defined and can be used in the current file without throwing a NameError.

当Python找到模块时,它将其绑定到本地范围内的名称。 这意味着现在已经定义了abc并且可以在当前文件中使用abc而不抛出NameError

If the name is never found, you’ll get a ModuleNotFoundError. You can find out more about imports in the Python documentation here!

如果未找到名称, ModuleNotFoundError收到ModuleNotFoundError 。 您可以在此处的Python文档中找到有关导入的更多信息!

Note: Security Concerns

注意:安全问题

Be aware that Python’s import system presents some significant security risks. This is largely due to its flexibility. For example, the module cache is writable, and it is possible to override core Python functionality using the import system. Importing from third-party packages can also expose your application to security threats.

请注意,Python的导入系统存在一些重大的安全风险。 这主要是由于其灵活性。 例如,模块缓存是可写的,并且可以使用导入系统覆盖Python的核心功能。 从第三方程序包导入还会使您的应用程序面临安全威胁。

Here are a couple of interesting resources to learn more about these security concerns and how to mitigate them:

以下是一些有趣的资源,以了解有关这些安全问题以及如何缓解这些问题的更多信息:

导入语句的语法 (Syntax of Import Statements)

Now that you know how import statements work, let’s explore their syntax. You can import both packages and modules. (Note that importing a package essentially imports the package’s __init__.py file as a module.) You can also import specific objects from a package or module.

现在您知道了导入语句的工作原理,让我们探究它们的语法。 您可以导入软件包和模块。 (请注意,导入软件包实际上是将软件包的__init__.py文件作为模块导入。)您还可以从软件包或模块中导入特定的对象。

There are generally two types of import syntax. When you use the first one, you import the resource directly, like this:

通常有两种类型的导入语法。 使用第一个资源时,可以直接导入资源,如下所示:

abc can be a package or a module.

abc可以是程序包或模块。

When you use the second syntax, you import the resource from another package or module. Here’s an example:

当您使用第二种语法时,您将从另一个包或模块中导入资源。 这是一个例子:

 from from abc abc import import xyz
xyz

xyz can be a module, subpackage, or object, such as a class or function.

xyz可以是模块,子包或对象,例如类或函数。

You can also choose to rename an imported resource, like so:

您还可以选择重命名导入的资源,如下所示:

This renames the imported resource abc to other_name within the script. It must now be referenced as other_name, or it will not be recognized.

这会将导入的资源abc重命名为脚本中的other_name 。 现在必须将其引用为other_name ,否则将无法识别它。

导入声明的样式 (Styling of Import Statements)

PEP 8, the official style guide for Python, has a few pointers when it comes to writing import statements. Here’s a summary:

PEP 8 是Python的官方样式指南,在编写导入语句时有一些提示。 总结如下:

  1. Imports should always be written at the top of the file, after any module comments and docstrings.

  2. Imports should be divided according to what is being imported. There are generally three groups:

    • standard library imports (Python’s built-in modules)
    • related third party imports (modules that are installed and do not belong to the current application)
    • local application imports (modules that belong to the current application)
  3. Each group of imports should be separated by a blank space.

  1. 导入应始终写在文件顶部,在任何模块注释和文档字符串之后。

  2. 进口应根据进口的物品进行划分。 通常分为三类:

    • 标准库导入(Python的内置模块)
    • 相关的第三方导入(已安装但不属于当前应用程序的模块)
    • 本地应用程序导入(属于当前应用程序的模块)
  3. 每组导入都应以空格分隔。

It’s also a good idea to order your imports alphabetically within each import group. This makes finding particular imports much easier, especially when there are many imports in a file.

在每个导入组中按字母顺序对导入进行排序也是一个好主意。 这使查找特定的导入变得容易得多,尤其是当文件中有很多导入时。

Here’s an example of how to style import statements:

以下是如何设置导入语句样式的示例:

 """Illustration of good import statement styling.

"""Illustration of good import statement styling.

Note that the imports come after the docstring.

Note that the imports come after the docstring.

"""

"""

# Standard library imports
# Standard library imports
import import datetime
datetime
import import os

os

# Third party imports
# Third party imports
from from flask flask import import Flask
Flask
from from flask_restful flask_restful import import Api
Api
from from flask_sqlalchemy flask_sqlalchemy import import SQLAlchemy

SQLAlchemy

# Local application imports
# Local application imports
from from local_module local_module import import local_class
local_class
from from local_package local_package import import local_function
local_function

The import statements above are divided into three distinct groups, separated by a blank space. They are also ordered alphabetically within each group.

上面的import语句分为三个不同的组,用空格隔开。 在每个组中,它们也按字母顺序排列。

绝对进口 (Absolute Imports)

You’ve gotten up to speed on how to write import statements and how to style them like a pro. Now it’s time to learn a little more about absolute imports.

您已经掌握了如何编写导入语句以及如何像专家一样设置它们的风格。 现在是时候学习更多有关绝对导入的知识了。

An absolute import specifies the resource to be imported using its full path from the project’s root folder.

绝对导入使用项目的根文件夹中的完整路径指定要导入的资源。

语法和实际示例 (Syntax and Practical Examples)

Let’s say you have the following directory structure:

假设您具有以下目录结构:

There’s a directory, project, which contains two sub-directories, package1 and package2. The package1 directory has two files, module1.py and module2.py.

有一个目录project ,它包含两个子目录package1package2package1目录包含两个文件module1.pymodule2.py

The package2 directory has three files: two modules, module3.py and module4.py, and an initialization file, __init__.py. It also contains a directory, subpackage, which in turn contains a file, module5.py.

package2目录包含三个文件:两个模块module3.pymodule4.py ,以及初始化文件__init__.py 。 它还包含一个目录subpackage ,该目录又包含一个文件module5.py

Let’s assume the following:

让我们假设以下内容:

  1. package1/module2.py contains a function, function1.
  2. package2/__init__.py contains a class, class1.
  3. package2/subpackage1/module5.py contains a function, function2.
  1. package1/module2.py包含一个函数function1
  2. package2/__init__.py包含一个类class1
  3. package2/subpackage1/module5.py包含一个函数function2

The following are practical examples of absolute imports:

以下是绝对导入的实际示例:

 from from package1 package1 import import module1
module1
from from package1.module2 package1.module2 import import function1
function1
from from package2 package2 import import class1
class1
from from package2.subpackage1.module5 package2.subpackage1.module5 import import function2
function2

Note that you must give a detailed path for each package or file, from the top-level package folder. This is somewhat similar to its file path, but we use a dot (.) instead of a slash (/).

请注意,您必须从顶级程序包文件夹中为每个程序包或文件提供详细的路径。 这有点类似于它的文件路径,但是我们使用点( . )而不是斜杠( / )。

绝对进口的利与弊 (Pros and Cons of Absolute Imports)

Absolute imports are preferred because they are quite clear and straightforward. It is easy to tell exactly where the imported resource is, just by looking at the statement. Additionally, absolute imports remain valid even if the current location of the import statement changes. In fact, PEP 8 explicitly recommends absolute imports.

绝对导入是首选,因为它们非常清楚和直接。 仅通过查看语句,就可以很容易地准确知道导入的资源在哪里。 此外,即使import语句的当前位置发生更改,绝对导入仍然有效。 实际上,PEP 8明确建议绝对导入。

Sometimes, however, absolute imports can get quite verbose, depending on the complexity of the directory structure. Imagine having a statement like this:

但是,有时绝对导入可能会变得非常冗长,具体取决于目录结构的复杂性。 想象一下这样的声明:

That’s ridiculous, right? Luckily, relative imports are a good alternative in such cases!

太荒谬了吧? 幸运的是,在这种情况下,相对进口是一个不错的选择!

相对进口 (Relative Imports)

A relative import specifies the resource to be imported relative to the current location—that is, the location where the import statement is. There are two types of relative imports: implicit and explicit. Implicit relative imports have been deprecated in Python 3, so I won’t be covering them here.

相对导入指定相对于当前位置(即,导入语句所在的位置)的要导入的资源。 相对导入有两种类型:隐式和显式。 隐式相对导入已在Python 3中弃用,因此在此不再赘述。

语法和实际示例 (Syntax and Practical Examples)

The syntax of a relative import depends on the current location as well as the location of the module, package, or object to be imported. Here are a few examples of relative imports:

相对导入的语法取决于当前位置以及要导入的模块,包或对象的位置。 以下是相对导入的一些示例:

 from from .some_module .some_module import import some_class
some_class
from from ..some_package ..some_package import import some_function
some_function
from from . . import import some_class
some_class

You can see that there is at least one dot in each import statement above. Relative imports make use of dot notation to specify location.

您可以看到上面的每个import语句中至少有一个点。 相对导入使用点符号来指定位置。

A single dot means that the module or package referenced is in the same directory as the current location. Two dots mean that it is in the parent directory of the current location—that is, the directory above. Three dots mean that it is in the grandparent directory, and so on. This will probably be familiar to you if you use a Unix-like operating system!

单点表示所引用的模块或软件包与当前位置位于同一目录中。 两个点表示它位于当前位置的父目录中,即上面的目录中。 三个点表示它位于祖父母目录中,依此类推。 如果您使用类似Unix的操作系统,这可能对您来说很熟悉!

Let’s assume you have the same directory structure as before:

假设您具有与以前相同的目录结构:

Recall the file contents:

调出文件内容:

  1. package1/module2.py contains a function, function1.
  2. package2/__init__.py contains a class, class1.
  3. package2/subpackage1/module5.py contains a function, function2.
  1. package1/module2.py包含一个函数function1
  2. package2/__init__.py包含一个类class1
  3. package2/subpackage1/module5.py包含一个函数function2

You can import function1 into the package1/module1.py file this way:

您可以通过以下方式将function1导入package1/module1.py文件:

 # package1/module1.py

# package1/module1.py

from from .module2 .module2 import import function1
function1

You’d use only one dot here because module2.py is in the same directory as the current module, which is module1.py.

您在这里只使用一个点,因为module2.py与当前模块位于相同的目录module1.py

You can import class1 and function2 into the package2/module3.py file this way:

您可以通过以下方式将class1function2导入package2/module3.py文件:

In the first import statement, the single dot means that you are importing class1 from the current package. Remember that importing a package essentially imports the package’s __init__.py file as a module.

在第一个import语句中,单点表示您正在从当前包中导入class1 。 请记住,导入程序包实际上__init__.py程序包的__init__.py文件作为模块导入。

In the second import statement, you’d use a single dot again because subpackage1 is in the same directory as the current module, which is module3.py.

在第二个import语句中,您将再次使用一个点,因为subpackage1与当前模块位于相同的目录module3.py

相对进口的利与弊 (Pros and Cons of Relative Imports)

One clear advantage of relative imports is that they are quite succinct. Depending on the current location, they can turn the ridiculously long import statement you saw earlier to something as simple as this:

相对进口的一个明显优势是它们非常简洁。 根据当前位置,他们可以将您之前看到的可笑的冗长的import语句变成如下所示的简单内容:

 from from ..subpackage4.module5 ..subpackage4.module5 import import function6
function6

Unfortunately, relative imports can be messy, particularly for shared projects where directory structure is likely to change. Relative imports are also not as readable as absolute ones, and it’s not easy to tell the location of the imported resources.

不幸的是,相对导入可能会很混乱,尤其是对于目录结构可能会更改的共享项目。 相对导入也不如绝对导入更易读,而且很难说出导入资源的位置。

结论 (Conclusion)

Good job for making it to the end of this crash course on absolute and relative imports! Now you’re up to speed on how imports work. You’ve learned the best practices for writing import statements, and you know the difference between absolute and relative imports.

在绝对和相对进口方面速成教程的结尾,做得很好! 现在,您可以加快导入的工作速度。 您已经了解了编写导入语句的最佳实践,并且知道绝对导入和相对导入之间的区别。

With your new skills, you can confidently import packages and modules from the Python standard library, third party packages, and your own local packages. Remember that you should generally opt for absolute imports over relative ones, unless the path is complex and would make the statement too long.

借助您的新技能,您可以放心地从Python标准库,第三方程序包和您自己的本地程序包中导入程序包和模块。 请记住,通常您应该选择绝对导入而不是相对导入,除非路径复杂并且会使语句过长。

Thanks for reading!

谢谢阅读!

翻译自: https://www.pybloggers.com/2018/09/absolute-vs-relative-imports-in-python/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值