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

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

问题描述

假设我有以下文件,

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

现在,如果我运行main.py,它会显示"Package's string module imported".

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".

从技术上讲这是正确的吗?

Is this technically correct?

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包中使用import time,则会在标准库time模块之前找到pkg/time.py.相反,请使用 explicit 相对模块引用的Python 3模型;将from __future__ import absolute_import添加到所有文件中,然后使用from . import <name>明确指出从何处导入模块.

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天全站免登陆