python - 当 Python 从命令行运行时导入 urllib.parse 失败

标签 python command-line ipython python-3.4 attributeerror

我在 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) 在您的命名空间中。除此之外,该子模块必须 已经加载(导入)。来自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.

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

您不导入 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的副作用(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)'

关于python - 当 Python 从命令行运行时导入 urllib.parse 失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34494322/

相关文章:

python - 用于 python 类型提示检查的控制台工具

linux - 在 bash 脚本中设置变量

ios - 是否可以使用 xcodebuild 完全不用 Xcode 来开发 iOS 应用程序?

javascript - 如何在 tensorflow.js 中使用图像作为输入?

Python - 具有 0.99 和 0.999 不同颜色的自定义颜色图

python - 在 django 中使用模型多重继承时如何修复字段冲突

c++ - 如何从命令行捕获 exe 崩溃

python - 为什么我的图表是一个疯狂闪烁的怪物?

python - 如何在 ipython 提示符中显示当前目录

ipython - 当我按下回车键时,让 ipython 总是执行命令?