Python: why does importing a package sometimes grant access to modules underneath it but sometimes not?(为什么导入包有时会授予对其下模块的访问权限,但有时不会?)
问题描述
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'
这两个版本都是3.6.1。
有什么不同?好的做法是什么?
编辑以合并@user2357112和@Tomoki的答案。
直接从@user2357112
要使对urllib.parse的访问起作用,必须满足以下两个条件:
urllib
模块对象必须绑定到urllib
名称,无论是在本地、全局还是某个封闭作用域中。urllib.parse
子模块必须已初始化并绑定到urllib
模块对象的parse属性。 当前本地或全局作用域(或任何封闭作用域)中的导入urllib
满足第一个条件。在程序中的任何位置执行的
import urllib.parse
满足第二个条件,因为它加载子模块并将其绑定到urllib
模块对象上的parse
属性,而整个程序只有一个urllib
模块对象。在简单导入
urllib
后可以访问urllib.parse
的环境中,一定已经加载了urllib.parse
,使您可以看到它。
证据由@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
属性。
当前本地或全局作用域(或任何封闭作用域)中的import urllib
满足第一个条件。
在程序中的任何位置执行的import urllib.parse
满足第二个条件,因为它加载子模块并将其绑定到urllib
模块对象上的parse
属性,而整个程序只有一个urllib
模块对象。
在简单的import urllib
之后可以访问urllib.parse
的环境中,一定有其他代码加载了urllib.parse
,使您可以看到它。
这篇关于为什么导入包有时会授予对其下模块的访问权限,但有时不会?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:为什么导入包有时会授予对其下模块的访问权限,但有时不会?
基础教程推荐
- 将 YAML 文件转换为 python dict 2022-01-01
- 哪些 Python 包提供独立的事件系统? 2022-01-01
- 合并具有多索引的两个数据帧 2022-01-01
- 使用 Google App Engine (Python) 将文件上传到 Google Cloud Storage 2022-01-01
- 如何在 Python 中检测文件是否为二进制(非文本)文 2022-01-01
- 使 Python 脚本在 Windows 上运行而不指定“.py";延期 2022-01-01
- 使用Python匹配Stata加权xtil命令的确定方法? 2022-01-01
- 如何在Python中绘制多元函数? 2022-01-01
- 症状类型错误:无法确定关系的真值 2022-01-01
- Python 的 List 是如何实现的? 2022-01-01