为什么"导入模块"然后"从包导入模块"再次加载模块?

Ben*_*oyt 13 python module package python-import

我的PYTHONPATH中有一个看起来像这样的包:

package/
    __init__.py
    module.py
        print 'Loading module'
Run Code Online (Sandbox Code Playgroud)

如果我从package/目录运行Python (或在此目录中编写另一个模块)并键入

import module
Run Code Online (Sandbox Code Playgroud)

它加载module.py并按预期打印出"加载模块".但是,如果我再输入

from package import module
Run Code Online (Sandbox Code Playgroud)

它加载module.py并再次打印"加载模块" ,这是我没想到的.这是什么理由?

注意:我认为我从技术上理解为什么Python会这样做,因为sys.modules键import module只是"module",但是对于from package import module它来说"package.module".所以我想我想知道的是为什么密钥在这里是不同的 - 为什么文件的路径名不是用作密钥,以便Python做到人们期望的呢?

Gly*_*yph 2

实际上,通过从package目录运行代码,您已经错误配置了 Python。您不应该将该目录放在 上sys.path,因为它位于包内。

Python 不使用文件名作为键,因为它不是导入文件,而是导入模块。允许人们这样做import c:\jim\my files\projects\code\stuff会鼓励各种肮脏的行为。

考虑一下这种情况:如果你当时在~/foo/package/并且~/barPYTHONPATH- 但 ~/bar 只是一个符号链接呢~/foo?您是否希望 Python 能够解析符号链接,然后为您删除重复的符号链接?如果将相对目录放在 PYTHONPATH 上,然后更改目录会怎样?如果“foo.py”是“bar.py”的符号链接怎么办?您是否期望这两者也能被删除重复数据?如果它们不是符号链接,而只是精确的副本怎么办?添加复杂的规则来试图在模棱两可的情况下做一些方便的事情意味着它会做一些对其他人来说非常不方便的事情。(Python 禅宗 12:面对歧义,拒绝猜测的诱惑。)

Python 在这里做了一些简单的事情,您有责任确保环境设置正确。现在,您可能会争辩说,默认情况下放置当前目录并不是一个好主意PYTHONPATH- 我什至可能同意您的观点 - 但鉴于它在那里,它应该遵循与其他路径条目相同的一致规则集。如果打算从任意目录运行,您的应用程序始终可以通过sys.pathsys.path.remove('').