隐式相对导入如何在 Python 中工作? [英] How do implicit relative imports work in Python?

查看:18
本文介绍了隐式相对导入如何在 Python 中工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有以下文件,

pkg/
pkg/__init__.py
pkg/main.py # import string
pkg/string.py # print("Package's string module imported")

现在,如果我运行 main.py,它会显示 Package 的字符串模块已导入".

Now, if I run main.py, it says "Package's string module imported".

这是有道理的,它按照此链接中的声明工作一个>:

This makes sense and it works as per this statement in this link:

它会首先查看包的目录"

"it will first look in the package's directory"

假设我稍微修改了文件结构(添加了一个核心目录):

Assume I modified the file structure slightly (added a core directory):

pkg/
pkg/__init__.py
plg/core/__init__.py
pkg/core/main.py # import string
pkg/string.py # print("Package's string module imported")

现在,如果我运行 python core/main.py,它会加载内置的 string 模块.

Now, if I run python core/main.py, it loads the built-in string module.

在第二种情况下,如果它必须遵守声明它将首先查看包的目录"它不应该加载本地string.py 因为 pkg 是包目录"?

In the second case too, if it has to comply with the statement "it will first look in the package's directory" shouldn't it load the local string.py because pkg is the "package directory"?

我对包目录"一词的理解是特别根文件夹集合__init__.py文件夹.所以在这种情况下,pkg 是包目录".它适用于 main.py 以及 core/main.py 等子目录中的文件,因为它是这个包"的一部分.

My sense of the term "package directory" is specifically the root folder of a collection of folders with __init__.py. So in this case, pkg is the "package directory". It is applicable to main.py and also files in sub- directories like core/main.py because it is part of this "package".

这在技术上正确吗?

PS:代码片段中#之后是文件的实际内容(没有前导空格).

PS: What follows after # in the code snippet is the actual content of the file (with no leading spaces).

推荐答案

包是带有 __init__.py 文件的目录,是的,当在模块上找到时,会作为模块加载搜索路径.所以 pkg 只是一个包,你可以导入并当作包如果父目录在模块搜索路径上.

Packages are directories with a __init__.py file, yes, and are loaded as a module when found on the module search path. So pkg is only a package that you can import and treat as a package if the parent directory is on the module search path.

但是通过将 pkg/core/main.py 文件作为 script 运行,Python 将 pkg/core 目录添加到模块中搜索路径,而不是 pkg 的父目录.现在您的模块搜索路径上确实有一个 __init__.py 文件,但这不是定义包的内容.你只有一个 __main__ 模块,与其他任何东西都没有包关系,你不能依赖隐式相对导入.

But by running the pkg/core/main.py file as a script, Python added the pkg/core directory to the module search path, not the parent directory of pkg. You do have a __init__.py file on your module search path now, but that's not what defines a package. You merely have a __main__ module, there is no package relationship to anything else, and you can't rely on implicit relative imports.

您有三个选择:

  1. 不要将包内的文件作为脚本运行.将脚本文件外部放在您的包中,并根据需要导入您的包.你可以把它next放到pkg目录下,或者确保pkg目录首先安装到模块搜索路径上已经存在的目录中,或者让您的脚本计算添加到 sys.path 的正确路径.

  1. Do not run files inside packages as scripts. Put a script file outside of your package, and have that import your package as needed. You could put it next to the pkg directory, or make sure the pkg directory is first installed into a directory already on the module search path, or by having your script calculate the right path to add to sys.path.

使用-m 命令行开关 像运行脚本一样运行模块.如果您使用 python -m pkg.core,Python 将查找 __main__.py 文件并将其作为脚本运行.-m 开关会将当前工作目录添加到您的模块搜索路径中,因此您可以在正确的工作目录中使用该命令,一切都会正常进行.或者将您的软件包安装在模块搜索路径上已经存在的目录中.

Use the -m command line switch to run a module as if it is a script. If you use python -m pkg.core Python will look for a __main__.py file and run that as a script. The -m switch will add the current working directory to your module search path, so you can use that command when you are in the right working directory and everything will work. Or have your package installed in a directory already on the module search path.

让您的脚本将正确的目录添加到模块搜索路径中(基于 os.path.absolute(__file__) 获取当前文件的路径).考虑到您的脚本总是名为 __main__,并且导入 pkg.core.main 会添加第二个独立的模块对象;你会有两个独立的命名空间.

Have your script add the right directory to the module search path (based on os.path.absolute(__file__) to get a path to the current file). Take into account that your script is always named __main__, and importing pkg.core.main would add a second, independent module object; you'd have two separate namespaces.

我也强烈建议不要使用隐式相对导入.您可以通过添加具有相同名称的嵌套包或模块来轻松屏蔽顶级模块和包.pkg/time.py 将在标准库 time 模块之前找到,如果您尝试在 pkg<中使用 import time/代码> 包.相反,使用显式相关模块引用的 Python 3 模型;将 from __future__ import absolute_import 添加到您的所有文件中,然后使用 from .import 明确说明您的模块是从哪里导入的.

I also strongly advice against using implicit relative imports. You can easily mask top-level modules and packages by adding a nested package or module with the same name. pkg/time.py would be found before the standard-library time module if you tried to use import time inside the pkg package. Instead, use the Python 3 model of explicit relative module references; add from __future__ import absolute_import to all your files, and then use from . import <name> to be explicit as to where your module is being imported from.

这篇关于隐式相对导入如何在 Python 中工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆