从另一个模块导入的访问节点在Python 3中

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

Access nodule imported from another module in Python 3

问题

我有以下Python 3项目:

- main.py
- mylib
    | - foo.py
    | - bar.py
    | - last.py

在foo.py中,我使用了绝对导入(import mylib.bar)导入的bar.py。

现在在main.py中,我有以下内容:

import mylib.foo
import mylib.last

result1 = mylib.foo.func()
result2 = mylib.last.func()
result3 = mylib.bar.func()

这段代码不会抛出任何错误,我不明白为什么。我没有在main.py中导入mylib.bar,所以最后一行不应该起作用。mylib.bar是在mylib.foo中导入的,而mylib.foo本身被main.py导入,但是命名空间不应该是分开的吗?为什么可以在main.py中使用mylib.bar而不导入它?

mylib.foo还使用了numpy,但是在main.py中没有可用numpy,因此为什么mylib.bar可用?

相同的行为也观察到了相对导入。我还尝试创建了__init__.py文件。

编辑:
我还将架构更改为:

- main.py
- foo.py
- bar.py
- last.py

在这种情况下,在导入foo时,main.py中不再可用bar。行为不同,似乎与使用子文件夹有关。

英文:

I have the following Python 3 project:

- main.py
- mylib
    | - foo.py
    | - bar.py
    | - last.py

In foo.py, I am using bar.py that I imported using absolut import (import mylib.bar).

Now in my main.py I have the following:

import mylib.foo
import mylib.last

result1 = mylib.foo.func()
result2 = mylib.last.func()
result3 = mylib.bar.func()

And this code does not throw any error and I do not understand why. I did not import mylib.bar in the main.py so the last line should not work. mylib.bar is imported in mylib.foo which itself is imported by main.py but isn't namespace supposed to be separated ? Why is it possible to use mylib.bar without importing in the main.py ?

mylib.foo is also using numpy, but numpy is not available in main.py, therefore why is mylib.bar available ?

Same behavior is also observed with relative import. I also tried to create __init__.py file.

EDIT:
I also changed the architecture to:

- main.py
- foo.py
- bar.py
- last.py

I this case, bar is no longer available in the main.py when importing foo. The behavior is different and seems to be related to the use of a subfolder.

答案1

得分: 1

在Python中,当导入一个模块时,它的代码会被执行,并且生成的命名空间会被存储在sys.modules中。当你导入mylib.foo时,Python会执行mylib/foo.py中的代码,而该代码会导入mylib.bar。由于mylib.bar已经被导入(因为它被mylib.foo导入),Python将简单地从sys.modules中返回现有的命名空间。

因此,当你稍后在main.py中导入mylib.last时,Python会执行mylib/last.py中的代码,因为它已经被mylib.foo导入,所以它可以访问mylib.bar。

至于numpy,可能是由mylib.foo导入,但没有被mylib.last明确导入。在这种情况下,mylib.last仍然可以通过sys.modules中现有的命名空间访问numpy。但是,如果mylib.last尝试显式导入numpy,它会失败,因为numpy没有在该模块的命名空间中导入。

关于使用相对导入,重要的是确保当前包正确定义,包括在包目录中包含一个__init__.py文件。如果缺少这个文件,Python会将该包视为常规目录,相对导入可能不会按预期工作。

英文:

In Python, when a module is imported, its code is executed and the resulting namespace is stored in sys.modules. When you import mylib.foo, Python will execute the code in mylib/foo.py, which in turn imports mylib.bar. Since mylib.bar has already been imported (because it was imported by mylib.foo), Python will simply return the existing namespace from sys.modules.

Therefore, when you later import mylib.last in main.py, Python will execute the code in mylib/last.py, which has access to mylib.bar because it has already been imported by mylib.foo.

As for numpy, it is possible that it is imported by mylib.foo but not explicitly imported by mylib.last. In this case, mylib.last can still access numpy through the existing namespace in sys.modules. However, if mylib.last tries to import numpy explicitly, it will fail because numpy has not been imported in that module's namespace.

Regarding the use of relative imports, it is important to make sure that the current package is properly defined by including an init.py file in the package directory. If this file is missing, Python will treat the package as a regular directory and relative imports may not work as expected.

huangapple
  • 本文由 发表于 2023年3月7日 16:50:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/75659738.html
匿名

发表评论

匿名网友

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

确定