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

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

问题描述

我在python 3.4.2中观察到以下行为,我无法解释。希望有人可以在这件事上阐明一些事情:



在IPython中:

  In [129]:import urllib 

在[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)'
回溯(最近一次调用):
< module>中的文件< string>
AttributeError:'module'object没有属性'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 模块(实际上是 (不导入其子模块(解析,请求等)。



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


如果package spam 在导入$ b $后有一个子模块 foo b spam.foo spam 将有一个属性 foo 它绑定到
子模块。 [...]不变的控制是,如果你有
sys.modules ['spam'] sys.modules [ spam.foo'] (如上所述导入后将
),后者必须显示为 foo 属性$ b $


每个模块只有一个实例,因此对 urllib 模块对象(存储在 sys.modules ['urllib'] )无处不在。



您不要导入 urllib.parse ,但IPython 。创建启动文件:

  import urllib 
print('运行启动文件:',end = )
try:
#导入'urllib.parse'ANYWHERE后,
#'urllib'将具有'parse'属性。
#还可以做import sys; sys.modules ['urllib']。parse
urllib.parse
except AttributeError:
print(urllib.parse hasn'已导入)
else:
print('urllib.parse已经导入')
print('退出启动文件')

并启动 ipython



b
$ b

  vaultah @ base:〜$ ipython 
运行urllib / parse.py
运行启动文件:urllib.parse已导入
退出启动文件。
Python 3.6.0a0(默认值:089146b8ccc6,2015年9月25日,14:16:56)
键入copyright,credits或license了解更多信息。

IPython 4.0.0 - 增强的交互式Python。

这是导入 pydoc 在IPython启动期间(其中ipython / usr / local / bin / ipython ):


$ b $来自IPython导入的
start $ ip



$ b / usr / local / lib / python3.6 / site-packages / IPython / __ init__.py,第47行:
从.core.application导入应用程序
/usr/local/lib/python3.6/site-packages/IPython /core/application.py,第24行:
从IPython.core导入版本,crashhandler
/usr/local/lib/python3.6/site-packages/IPython/core/crashhandler.py,行28:
from IPython.core import ultratb
/usr/local/lib/python3.6/site-packages/IPython/core/ultratb.py,第90行:
import pydoc
/usr/local/lib/python3.6/pydoc.py,第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)'


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

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

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

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

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