从命令行运行 Python 时导入 urllib.parse 失败 [英] import urllib.parse fails when Python run from command line

查看:29
本文介绍了从命令行运行 Python 时导入 urllib.parse 失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 python 3.4.2 中观察到以下行为,我无法解释.希望有人能对此事有所了解:

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:

在 IPython 中:

In 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'>

我已经导入了一个模块,并打印了它的一个属性.一切都按预期工作.到目前为止,生活还不错.

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 "<string>", line 1, in <module>
AttributeError: 'module' object has no attribute 'parse'

说什么?!这不是应该的工作方式.
好吧,也许这是一个 python 范围的行为;使用 -c 标志时,可能不会立即导入模块.让我们尝试另一个模块:

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

什么?!它如何适用于 datetime 而不适用于 urllib?我在两个地方都使用相同版本的 python (3.4.2)

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?

编辑:

每一条评论:

$ 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) 无需导入它的子模块(解析、请求等).

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

如果您想使用属性访问访问其子模块,您需要父模块对象 (urllib) 位于您的命名空间中.除此之外,该子模块必须已经加载(导入).来自文档:

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:

如果包spam有子模块foo,导入后spam.foo, spam 将有一个属性 foo 绑定到子模块.[...] 不变的持有是,如果你有sys.modules['spam']sys.modules['spam.foo'](就像你在上述导入之后),后者必须作为 foo 属性出现前者.

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.

每个模块只有一个实例,因此对 urllib 模块对象(存储在 sys.modules['urllib'] 中)所做的任何更改都会在任何地方反映出来.

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.

您不导入 urllib.parse,但 IPython . 为了证明这一点,我将创建一个启动文件:

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

并启动 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的副作用(which ipython/usr/local/bin/ipython):

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

这解释了为什么下面的代码失败 - 你只导入 urllib 而似乎没有导入 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)'

另一方面,以下命令有效,因为datetime.datetime不是一个模块.这是一个在 import datetime 期间导入的类.

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

这篇关于从命令行运行 Python 时导入 urllib.parse 失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆