我在python 3.4.2中观察到以下行为,但无法解释。希望有人能对此事有所启发:
在IPython中:
In [129]: import urllib
In [130]: print(urllib.parse)
<module 'urllib.parse' from '/Users/ashwin/.pyenv/versions/3.4.2/lib/python3.4/urllib/parse.py'>
我已经导入了一个模块,并打印了其中一个属性。一切正常。到目前为止,生活还不错。
现在,我从命令行执行相同的操作:
$ python -c 'import urllib; print(urllib.parse)'
Traceback (most recent call last):
File "<string>", line 1, in <module>
AttributeError: 'module' object has no attribute 'parse'
说什么?!那不是应该的工作方式。
好的,也许这是python范围的行为;使用该-c
标志时,可能不会立即导入模块。让我们尝试另一个模块:
$ python -c 'import datetime; print(datetime.datetime)'
<class 'datetime.datetime'>
什么?!它如何工作datetime
而不是工作urllib
?我在两个地方都使用相同版本的python(3.4.2)
有人对此有任何想法吗?
编辑:
每条评论之一:
$ which -a ipython
/Users/ashwin/.pyenv/shims/ipython
/Library/Frameworks/Python.framework/Versions/2.7/bin/ipython
/usr/local/bin/ipython
/usr/local/bin/ipython
和
$ which -a python
/Users/ashwin/.pyenv/shims/python
/Library/Frameworks/Python.framework/Versions/2.7/bin/python
/usr/bin/python
/usr/bin/python
运行时import urllib
,它将创建urllib
模块(实际上是package)的模块对象,而无需导入其子模块(解析,请求等)。
urllib
如果要使用属性访问来访问其子模块,则需要将父模块对象()放在名称空间中。除此之外,该子模块必须已经加载(导入)。从文档中:
如果package
spam
包含一个子模块foo
,则在导入后spam.foo
,spam
将具有foo
绑定到该子模块的属性。[...]不变的条件是,如果您拥有sys.modules['spam']
andsys.modules['spam.foo']
(如在上述导入之后那样),则后者必须作为foo
前者的属性出现。
每个模块只有一个实例,因此对urllib
模块对象(存储在中sys.modules['urllib']
)的任何更改都会反映到各处。
你不进口urllib.parse
,但IPython的确实。为了证明这一点,我将创建一个启动文件:
import urllib
print('Running the startup file: ', end='')
try:
# After importing 'urllib.parse' ANYWHERE,
# 'urllib' will have the 'parse' attribute.
# You could also do "import sys; sys.modules['urllib'].parse"
urllib.parse
except AttributeError:
print("urllib.parse hasn't been imported yet")
else:
print('urllib.parse has already been imported')
print('Exiting the startup file.')
并启动 ipython
vaultah@base:~$ ipython
Running urllib/parse.py
Running the startup file: urllib.parse has already been imported
Exiting the startup file.
Python 3.6.0a0 (default:089146b8ccc6, Sep 25 2015, 14:16:56)
Type "copyright", "credits" or "license" for more information.
IPython 4.0.0 -- An enhanced Interactive Python.
这是在pydoc
IPython启动期间导入的副作用(which ipython
是/ usr / local / bin / ipython):
/usr/local/bin/ipython, line 7:
from IPython import start_ipython
/usr/local/lib/python3.6/site-packages/IPython/__init__.py, line 47:
from .core.application import Application
/usr/local/lib/python3.6/site-packages/IPython/core/application.py, line 24:
from IPython.core import release, crashhandler
/usr/local/lib/python3.6/site-packages/IPython/core/crashhandler.py, line 28:
from IPython.core import ultratb
/usr/local/lib/python3.6/site-packages/IPython/core/ultratb.py, line 90:
import pydoc
/usr/local/lib/python3.6/pydoc.py, line 68:
import urllib.parse
这解释了以下代码为何失败的原因-您仅导入urllib
而似乎没有导入urllib.parse
:
$ python -c 'import urllib; print(urllib.parse)'
另一方面,以下命令起作用,因为datetime.datetime
它不是模块。这是一个在期间导入的类import datetime
。
$ python -c 'import datetime; print(datetime.datetime)'
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句