加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Python > 正文

Python:为什么导入包有时会授予对它下面的模块的访问权限,但有

发布时间:2020-12-20 12:03:44 所属栏目:Python 来源:网络整理
导读:Python导入机制对我来说永远是个神话.有时导入包可以授予对其下方模块的访问权限.例如, import urlliburllib.parse.unquote 给 function urllib.parse.unquote 即使仅导入包(即本例中为urllib)但未向下导入模块文件,也显示函数是可访问的.这是在Jupyter笔记
Python导入机制对我来说永远是个神话.有时导入包可以授予对其下方模块的访问权限.例如,

import urllib
urllib.parse.unquote

<function urllib.parse.unquote>

即使仅导入包(即本例中为urllib)但未向下导入模块文件,也显示函数是可访问的.这是在Jupyter笔记本中完成的.

但是当我在终端做同样的事情时

>>> import urllib
>>> urllib.parse.unquote
Traceback (most recent call last):
  File "<stdin>",line 1,in <module>
AttributeError: module 'urllib' has no attribute 'parse'

两个Python版本都是3.6.1.

是什么造成了差异,什么是好的做法?

编辑将@ user2357112和@Tomoki的答案结合起来.

直接来自@ user2357112

For an access to urllib.parse to work,the following two conditions must be true:

The urllib module object must be bound to the urllib name,whether in the local,global,or some enclosing scope.
The urllib.parse submodule must have been initialized and bound to the parse attribute of the urllib module object.
An import urllib in the current local or global scope (or any enclosing scope) satisfies the first condition.

An import urllib.parse executed anywhere in the program satisfies the second condition,since it loads the submodule and binds it to the parse attribute on the urllib module object,and there’s only one urllib module object for the whole program.

In the environments where urllib.parse was accessible after a simple import urllib,some other code must have loaded urllib.parse,causing you to see it.

证据由@Tomoki提供

Test: "import IPython"
 └─IPython:┐
      ┌────┘
      ├──"from core.application import Application"
      │   └──IPython.core.application: "from IPython.core import release,crashhandler"
      │      └──IPython.core.crashhandler: "from IPython.core import ultratb"
      │         └──IPython.core.ultratb: "import pydoc"
      │            └──pydoc: "import urllib.parse"
      └──"from terminal.embed import embed"
          └──IPython.terminal.embed:┐
                        ┌───────────┘
                        ├──"from IPython.core import magic_arguments"
                        │   └──IPython.core.magic_arguments: "from IPython.utils.text import dedent"
                        │      └──IPython.utils.text: "from pathlib import Path"
                        │         └──pathlib: "from urllib.parse import quote_from_bytes"
                        ├──"from IPython.core.magic import Magics,magics_class,line_magic"
                        │   └──IPython.core.magic: "from IPython.core import oinspect"
                        │      └──IPython.core.oinspect: "from IPython.core import page"
                        │         └──IPython.core.page: "from IPython.core.display import display"
                        │            └──IPython.core.display: "import mimetypes"
                        │               └──mimetypes: "import urllib.parse"
                        └──"from IPython.terminal.interactiveshell import TerminalInteractiveShell"
                            └──pygments.plugin: "import pkg_resources"
                               └──pkg_resources: "import email.parser"
                                  └──email.parser: "from email.feedparser import FeedParser,BytesFeedParser"
                                     └──email.feedparser: "from email._policybase import compat32"
                                        └──email._policybase: "from email.utils import _has_surrogates"
                                           └──email.utils: "import urllib.parse"

最后一行确实触及了urllib.parse.

另一个证据

import scipy无法在终端或Jupyter笔记本中提供对scipy.stats.norm的访问,因为根本没有任何环境触及scipy.stats.

什么是好的做法?

我们可以从上面得出结论,这不仅是一种好的做法,而且实际上要求##导入整个模块级别##.

“始终导入到文件(模块)级别以保证访问”

谢谢大家的答案!

解决方法

要访问urllib.parse工作,必须满足以下两个条件:

> urllib模块对象必须绑定到urllib名称,无论是在本地,全局还是某些封闭范围内.
> urllib.parse子模块必须已初始化并绑定到urllib模块对象的parse属性.

当前本地或全局范围(或??任何封闭范围)中的导入urllib满足第一个条件.

在程序中的任何地方执行的导入urllib.parse都满足第二个条件,因为它加载子模块并将其绑定到urllib模块对象上的parse属性,并且整个程序只有一个urllib模块对象.

在简单导入urllib之后可以访问urllib.parse的环境中,其他一些代码必须加载urllib.parse,导致您看到它.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读