python urllib.parse_当Python从命令行运行时,import urllib.parse失败

I have observed the following behavior in python 3.4.2, and I am unableto explain it. Hopefully someone could shed some light on the matter:

In IPython:

In [129]: import urllib

In [130]: print(urllib.parse)

I've imported a module, and printed one of its attributes. Everything works as expected. So far, life is good.

Now, I do the same thing from the command line:

$ python -c 'import urllib; print(urllib.parse)'

Traceback (most recent call last):

File "", line 1, in

AttributeError: 'module' object has no attribute 'parse'

Say what?! that's not how that's supposed to work.

Ok, maybe this is a python-wide behavior; maybe modules are not immediately imported when using the -c flag. Let's try another module:

$ python -c 'import datetime; print(datetime.datetime)'

What?! How does it work for datetime and not for urllib? I'm using the same version of python in both places (3.4.2)

Does anyone have any thoughts on this?

EDIT:

Per one of the comments:

$ 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

And

$ which -a python

/Users/ashwin/.pyenv/shims/python

/Library/Frameworks/Python.framework/Versions/2.7/bin/python

/usr/bin/python

/usr/bin/python

解决方案

When you run import urllib, it creates the module object of the urllib module (which is actually a package) without importing its submodules (parse, request etc.).

You need the parent module object (urllib) to be in your namespace if you want to access its submodule using attribute access. In addition to that, that submodule must already be loaded (imported). From the documentation:

if package spam has a submodule foo, after importing

spam.foo, spam will have an attribute foo which is bound to the

submodule. [...] The invariant holding is that if you have

sys.modules['spam'] and sys.modules['spam.foo'] (as you would

after the above import), the latter must appear as the foo attribute

of the former.

There is only one instance of each module, thus any changes made to the urllib module object (stored in sys.modules['urllib']) get reflected everywhere.

You don't import urllib.parse, but IPython does. To prove this I'm going to create a startup file:

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.')

and launch 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.

It is the side effect of importing pydoc during the startup of IPython (which ipython is /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

This explains why the below code fails - you only import urllib and nothing seems to import urllib.parse:

$ python -c 'import urllib; print(urllib.parse)'

On the other hand, the following command works because datetime.datetime is not a module. It's a class that gets imported during import datetime.

$ python -c 'import datetime; print(datetime.datetime)'

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值