为什么要“导入模块"?然后“来自程序包导入模块"再次加载模块? [英] Why does "import module" and then "from package import module" load the module again?

查看:84
本文介绍了为什么要“导入模块"?然后“来自程序包导入模块"再次加载模块?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a package in my PYTHONPATH that looks something like this:

package/
    __init__.py
    module.py
        print 'Loading module'

如果我从package/目录运行Python(或在此目录中编写其他模块),然后键入

If I'm running Python from the package/ directory (or writing another module in this directory) and type

import module

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

it loads module.py and prints out "Loading module" as expected. However, if I then type

from package import module

它将加载module.py并再次打印正在加载模块" ,这是我所不希望的.这样做的理由是什么?

it loads module.py and prints "Loading module" again, which I don't expect. What's the rationale for this?

注意:我想我从技术上理解了Python为什么要这样做,因为import module的sys.modules密钥只是"module",而对于from package import module的sys.modules密钥是"package.module".因此,我想我想知道的是为什么键在这里与众不同-为什么不使用文件的路径名作为键,以便Python可以执行此处期望的操作?

Note: I think I understand technically why Python is doing this, because the sys.modules key for import module is just "module", but for from package import module it's "package.module". So I guess what I want to know is why the key is different here -- why isn't the file's path name used as the key so that Python does what one expects here?

推荐答案

有效地,通过运行package目录中的代码,您已经错误配置了Python.您不应该将该目录放在sys.path上,因为它位于软件包中.

Effectively, by running code from the package directory, you've misconfigured Python. You shouldn't have put that directory on sys.path, since it's inside a package.

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

Python doesn't use the filename as the key because it's not importing a file, it's importing a module. Allowing people to do 'import c:\jim\my files\projects\code\stuff' would encourage all kinds of nastiness.

请考虑这种情况:如果您位于~/foo/package/~/bar处于PYTHONPATH上怎么办-但是〜/bar仅仅是与~/foo的符号链接?您是否希望Python能够解决问题,然后为您删除符号链接的重复数据?如果将相对目录放在PYTHONPATH上,然后更改目录怎么办?如果'foo.py'是到'bar.py'的符号链接怎么办?您是否希望同时删除这两个数据?如果它们不是符号链接,而只是精确的副本,该怎么办?添加复杂的规则以尝试在模棱两可的情况下执行一些方便的操作,这意味着它对其他人造成了极大的不便. (Python zen 12:面对模棱两可,拒绝猜测的诱惑.)

Consider this case instead: what if you were in ~/foo/package/ and ~/bar were on PYTHONPATH - but ~/bar is just a symlink to ~/foo? Do you expect Python to resolve, then deduplicate the symbolic link for you? What if you put a relative directory on PYTHONPATH, then change directories? What if 'foo.py' is a symlink to 'bar.py'? Do you expect both of those to be de-duplicated too? What if they're not symlinks, but just exact copies? Adding complex rules to try to do something convenient in ambiguous circumstances means it does something highly inconvenient for other people. (Python zen 12: in the face of ambiguity, refuse the temptation to guess.)

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

Python does something simple here, and it's your responsibility to make sure that the environment is set up correctly. Now, you could argue that it's not a very good idea to put the current directory on PYTHONPATH by default - I might even agree with you - but given that it is there, it should follow the same consistent set of rules that other path entries do. If it's intended to be run from an arbitrary directory, your application can always remove the current directory from sys.path by starting off with sys.path.remove('').

这篇关于为什么要“导入模块"?然后“来自程序包导入模块"再次加载模块?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆