我在python 3.4.2中观察到以下行为,我无法解释它.希望有人可以解释一下这个问题:
在IPython中:
In [129]: import urllib
In [130]: print(urllib.parse)
我导入了一个模块,并打印了其中一个属性.一切都按预期工作.到目前为止,生活是美好的.
现在,我从命令行做同样的事情:
$python -c 'import urllib; print(urllib.parse)'
Traceback (most recent call last):
File "
说什么?!这不是应该如何工作的.
好吧,也许这是一个Python般的行为;使用-c标志时,可能不会立即导入模块.我们来试试另一个模块:
$python -c 'import datetime; print(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
如果要使用属性访问权限访问其子模块,则需要父模块对象(urllib)位于命名空间中.除此之外,必须已经加载(导入)该子模块.从documentation开始:
if package
spam
has a submodulefoo
,after importing
spam.foo
,spam
will have an attributefoo
which is bound to the
submodule. […] The invariant holding is that if you have
sys.modules['spam']
andsys.modules['spam.foo']
(as you would
after the above import),the latter must appear as thefoo
attribute
of the former.
每个模块只有一个实例,因此对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.
这是在IPython启动期间导入pydoc的副作用(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不是模块.它是在导入日期时导入的类.
$python -c 'import datetime; print(datetime.datetime)'