何时在相对导入中使用点?而m开关与此有什么关系?

huangapple go评论65阅读模式
英文:

When to put a dot in relative imports? And what does the m-switch have to do with it?

问题

我有一个简单的示例项目,其中包含以下文件:

folder
    __init__.py
    foo.py
    foobar.py
    script.py

foobar.py 中,使用 from .foo import foo 导入了函数 foo
(然后在函数 foobar 中使用它)。
script.py 中,使用 from .foobar import foobar 导入了函数 foobar
(然后执行它)。

但在导入语句中添加点号并不总是正确的选择。
根据脚本运行方式的不同,它们的存在可能会导致:
ImportError: attempted relative import with no known parent package(尝试相对导入但没有已知的父包)
或者它们的缺席可能会导致:
ModuleNotFoundError: No module named 'foobar'(没有名为 'foobar' 的模块)。

代码可以在 GitHub 上找到
(也有使用绝对路径的相同代码)。

使用点号

这对我需要的两种用例都有效:

  • 使用 m-switch 运行脚本:python -m project.folder.script
  • 在 Python 控制台中导入 foobarfrom project.folder.foobar import foobar

以下屏幕截图显示了如何运行脚本以及没有 m-switch 时的失败情况:

何时在相对导入中使用点?而m开关与此有什么关系?

不使用点号

幸运的是,没有必要在没有 m-switch 的情况下运行脚本。
(尽管这将很好,因为IDE有一个按钮用于执行此操作。)

以下屏幕截图显示了如何运行脚本以及没有 m-switch 时的失败情况:

何时在相对导入中使用点?而m开关与此有什么关系?

详细路径

似乎值得仔细查看所有情况下的 __name____file__
script.py__name__ 始终是字符串 __main__

何时在相对导入中使用点?而m开关与此有什么关系?

结论

对我来说,这似乎只是要使用点号和 m-switch。
(这只是轻微的烦恼,因为我的IDE不支持自动补全。)

但我仍然希望理解为什么有这两种实质上相同的做法。
人们常常说,点号用于向上导航目录(就像在HTML和PHP中的 ../)。
但这似乎不对,因为位置在两种情况下都是相同的。
(我们只是谈论同一文件夹中的相邻文件。)

这可能远不是关于这个主题的第一个问题。
我希望这足够清楚以弥补这种重复性。

英文:

I have a simple example project with these files:

folder
    __init__.py
    foo.py
    foobar.py
    script.py

In foobar.py the function foo is imported with from .foo import foo.<br>
(It is then used in the function foobar).<br>
In script.py the function foobar is imported with from .foobar import foobar.<br>
(It is then executed.)

But putting the dots in the import statement is not always the right choice.<br>
Depending on how the script is run, their presence can cause:<br>
ImportError: attempted relative import with no known parent package<br>
Or their absence can cause:<br>
ModuleNotFoundError: No module named &#39;foobar&#39;

The code can be found on GitHub. (There is also the same with absolute paths.)

with dots

This works for the two usecases that I need:

  • run script using the m-switch: python -m project.folder.script
  • import foobar in the Python console: from project.folder.foobar import foobar

This screenshot shows how running the script works with and fails without the m-switch:

何时在相对导入中使用点?而m开关与此有什么关系?

without dots

Gladly there is no need to run the script without the m-switch.<br>
(Although it would be nice, because the IDE has a button for that.)

This screenshot shows how running the script fails with and works without the m-switch:

何时在相对导入中使用点?而m开关与此有什么关系?

paths in detail

It seems worthwhile to take a closer look at __name__ and __file__ in all cases.<br>
__name__ of _script.py is always the string &#39;__main__&#39;.

何时在相对导入中使用点?而m开关与此有什么关系?

conclusion

Apparently for me this just boils down to having to use the dot and the m-switch.<br>
(This is just mildly annoying, because my IDE does not have auto-completion for it.)

But I would still like to understand, why there are these two ways of doing essentially the same thing.
People often say, that the dot is for going up a directory (like ../ in HTML and PHP).<br>
But there is something wrong with that, because the location is the same in both cases.<br>
(We just talk about neighboring files in the same folder.)

This must be far from the first question about this topic.<br>
I hope it is clear enough to compensate for that redundancy.

答案1

得分: 1

让我解释一下为什么点号很有用以及何时使用它。

  1. 在创建更复杂的项目时(比如使用Django或flask创建网站)点号非常有用。

  2. 我会简单地解释一下在导入语句前面加点号的最简单方法,基本上它将文件目录添加到您的代码导入目录中,让我解释一下。

当您通过 script.py 进行导入时,您的当前目录是:folder

为什么没有点号也能工作: 如果您在导入语句前面没有加点号,基本上是在告诉Python从与您的 script.py 相同的目录中导入 foo.py

为什么使用点号会报错:
因为您没有使用 main.py 运行您的代码(主文件将位于您的文件夹之外,但在相同的目录中)。 Python 将您的 script.py 视为您的 __main__,这意味着您不能在 script.py 中使用点号导入。这是因为您没有告诉Python要从哪个文件/文件夹导入 foobar。

如果您有一个 main.py,在导入语句中写上 from .foobar import foobar,基本上相当于写上这行代码:from folder.foobar import foobar。这是正确的做法。

注意:(这将要求您在 main.py 中写上 import folder,并在 __init__.py 中写上 from . import script

对于您的代码,请不要在导入语句前面使用点号,也不要使用 -m 开关。

我建议您可以在与您的 folder 相同的目录中创建一个 main.py,这样可以让您在以后创建更复杂的脚本时少一些麻烦。(在这种情况下,您必须在 folder 中的所有代码中加上点号)。

英文:

Let me explain why the dot is useful and when its used.

  1. The dot is really useful when you are creating more complex projects (like a website using Django or flask).

  2. The simplest way to I would explain the dot in front of imports is that it basically adds the file directory into your codes import directories, let me explain.

your current directory when you are importing through script.py is: folder.

Why without dot it works: If you don't have the dot in front of your import, you are basically telling Python to import foo.py from the same directory as your script.py

Why using dot it throws an error:
Because you don't use a main.py to run your code (the main file would be outside of your folder but in the same directory). Python considers your script.py as your __main__, This means that you cannot use the dot in imports that are in your script.py. This is because you haven't told Python which is the file/folder from which to import foobar.

If you would have a main.py, when importing the line from .foobar import foobar you are basically writing the line: from folder.foobar import foobar. Which would be correct.

Note: (This would require you to write import folder inside your main.py, and write from . import script inside your __init__.py)

for your code, don't use the dot in front of imports and don't use the m-switch.

I suggest that you could make a main.py in the same directory as your folder, this would make it possible for you to create a more complex script without a big headache later on. (In this case you have to add the dot in all of your code inside the folder)

huangapple
  • 本文由 发表于 2023年7月13日 19:14:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/76678733.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定