为什么我的Python导入不起作用?

7 投票
5 回答
32092 浏览
提问于 2025-04-16 14:37

这个是可以正常工作的:

from story.apps.document import core
print core.submit()

这个就不行:

from story import apps
print apps.document.core.submit()

“story”是一个文件夹。在这个文件夹里,有一个叫“apps”的文件夹。在“apps”文件夹里,还有一个叫“document”的文件夹。而“core.py”是一个文件。

每个文件夹里都有一个叫__init__.py的文件。

5 个回答

1

这只有在 story/__init__.py 文件里导入了 apps 的时候才有效。

7

当你写 story.apps.document import core 时,你是在告诉Python解释器去找一个叫 story.apps.document 的模块,把它导入进来,然后把这个模块里的 core 变量加载到你现在的环境中。

因为 core 是一个文件模块,它的命名空间里有这个文件中定义的变量,比如 submit


当你写 from story import apps 时,你是在告诉Python解释器去找一个叫 story 的模块,把它导入进来,然后把这个模块里的 apps 变量加载到你现在的环境中。

因为 apps 是一个目录模块,它的命名空间里有在它的 __init__.py 文件和这个目录下其他模块中定义的变量。所以 apps 知道 document 的存在,但它对 document 里的子模块 core 一无所知。


顺便说一下: 有时候人们会感到困惑的原因就是因为像这样的事情...

这个可以正常工作:

# File1
import story.apps.document
story.apps.document.core()

这个不行:

# File2
import story
story.apps.document.core() # <-- Looks like the same function call, but is an Error

对于 file1,导入可以正常工作,因为 import 操作会智能地在文件系统中查找东西。函数调用可以工作是因为模块 document 已经被导入,它的名字就是 story.apps.document

对于 file2,函数调用不工作是因为点操作符并没有智能,它只是试图访问Python对象的属性——它对文件系统或模块一无所知。

8

__init__.py 文件的作用是告诉 Python 把这个文件夹当作一个包来处理,但它并不一定会告诉 Python 自动导入这个文件夹里的子包或其他文件(不过如果你在里面加上合适的 import 语句,它是可以做到的)。

在有很多层级的包时,通常更好的是需要手动导入子包。

撰写回答