Python从命令行

时间:2015-10-19 04:16:53

标签: 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'

说什么?!这不是应该如何工作的。
好吧,也许这是一个蟒蛇般的行为;使用-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

2 个答案:

答案 0 :(得分:3)

运行import urllib时,它会创建urllib模块的模块对象(实际上是package而不导入其子模块(解析,请求等)。

如果要使用属性访问权限访问其子模块,则需要父模块对象(urllib)位于命名空间中。除此之外,该子模块必须已经加载(导入)。来自documentation

  

如果包spam在导入后具有子模块foo   spam.foospam将拥有绑定到的foo属性   子模块。 [...]不变的控股是,如果你有   sys.modules['spam']sys.modules['spam.foo'](正如您所愿   在上述导入之后),后者必须显示为foo属性   前者。

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

您不会导入urllib.parse,但IPython 为了证明这一点,我要创建一个启动文件:< / p>

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

答案 1 :(得分:0)

从Python 3开始,

urllib.parse可用。我想你可能需要import urllib.parse,而不是import urllib。不确定子模块导入(何时)是隐式的。

我猜测IPython会在启动时导入urllib.parse,这就是它可用的原因。

parse是一个模块而非属性:

Python 3.4.2 (default, Oct 15 2014, 22:01:37)
[GCC 4.2.1 Compatible Apple LLVM 5.1 (clang-503.0.40)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import urllib
>>> urllib.parse
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'parse'
>>> import urllib.parse
>>> urllib.parse
<module 'urllib.parse' from '/opt/local/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/urllib/parse.py'>