[python] `from ... import` vs`import .`


Answers

很多人已經解釋過關於importimport ,所以我想嘗試在實際區別的基礎上進行更多解釋。

首先,讓我解釋一下基本進口報表的確切含義。

import X

導入模塊X ,並在當前名稱空間中創建對該模塊的引用。 然後,您需要定義完成的模塊路徑以從模塊內部訪問特定屬性或方法(例如: X.nameX.attribute

from X import *

導入模塊X ,並在當前命名空間中創建對由該模​​塊定義的所有公共對象的引用(即,沒有以_開頭的名稱的所有內容)或您提及的任何名稱。

換句話說,在你運行這個語句之後,你可以簡單地使用一個普通的(非限定的)名稱來引用在模塊X定義的東西。 但X本身沒有定義,所以X.name不起作用。 如果name已經定義,它將被新版本取代。 如果X名稱更改為指向某個其他對象,則您的模塊將不會注意到。

這使得該模塊中的所有名稱都可在本地名稱空間中使用。

現在讓我們看看我們import XY時會發生什麼:

>>> import sys
>>> import os.path

使用name osos.path檢查sys.modules

>>> sys.modules['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> sys.modules['os.path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>

使用name osos.path檢查globals()locals()命名空間字典:

 >>> globals()['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> locals()['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> globals()['os.path']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'os.path'
>>>    

從上面的例子中,我們發現只有os被添加到本地和全局命名空間。 所以,我們應該可以使用os

 >>> os
 <module 'os' from     
  '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
 >>> os.path
 <module 'posixpath' from      
 '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
 >>>

...但不是path

>>> path
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'path' is not defined 
>>>

一旦從locals()名稱空間中刪除了os ,即使它們存在於sys.modules ,也將無法訪問osos.path

>>> del locals()['os']
>>> os
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'os' is not defined
>>> os.path
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'os' is not defined
>>>

現在讓我們來看看。

from

>>> import sys
>>> from os import path

使用name osos.path檢查sys.modules

>>> sys.modules['os']
<module 'os' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/os.pyc'>
>>> sys.modules['os.path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>

所以sys.modules看起來和我們使用import name

好的。 我們來看看它的locals()globals()命名空間字典是什麼樣的:

>>> globals()['path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> locals()['path']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> globals()['os']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'os'
>>>

您可以通過使用path訪問,但不能通過os.path

>>> path
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> os.path
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'os' is not defined
>>>

讓我們從locals()中刪除'path':

>>> del locals()['path']
>>> path
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'path' is not defined
>>>

最後一個使用別名的例子是:

>>> from os import path as HELL_BOY
>>> locals()['HELL_BOY']
<module 'posixpath' from '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>> globals()['HELL_BOY']
<module 'posixpath' from /System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/posixpath.pyc'>
>>>

並沒有定義路徑:

>>> globals()['path']
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
KeyError: 'path'
>>>

from使用的一個陷阱

當您從兩個不同的模塊導入相同的name

>>> import sys
>>> from os import stat
>>> locals()['stat']
<built-in function stat>
>>>
>>> stat
<built-in function stat>

再次從shutil導入stat:

>>>
>>> from shutil import stat
>>> locals()['stat']
<module 'stat' from 
'/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/stat.pyc'>
>>> stat
<module 'stat' from 
'/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/stat.pyc'>
>>>

最後的進口將贏得勝利

Question

這個問題在這裡已經有了答案:

我想知道代碼片段之間是否有區別

from urllib import request

和片段

import urllib.request

或者如果它們可以互換。 如果它們是可互換的,那麼這是“標準”/“首選”語法(如果有的話)?

謝謝!




在Python 2.x中,至少不能import urllib2.urlopen

你必須from urllib2 import urlopen

Python 2.6.5 (r265:79063, Apr 16 2010, 13:09:56)
[GCC 4.4.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import urllib2.urlopen
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named urlopen
>>> import urllib.request
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named request
>>>



它們是有區別的。 在某些情況下,其中一個會起作用,另一個則不行。 這裡是一個例子:假設我們有以下結構:

foo.py
mylib\
    a.py
    b.py

現在,我想將b.py導入到a.py. 我想將a.py導入到foo中。 我該怎麼做呢? 兩個陳述:在我寫:

import b

foo.py我寫道:

import mylib.a

那麼,當試圖運行foo.py時會產生一個ImportError。 口譯員會抱怨a.py中的import語句(import b),說沒有模塊b。 那麼如何解決這個問題呢? 在這種情況下,更改a中的import語句以導入mylib.b將不起作用,因為a和b都在lib中。 這裡的解決方案(或至少一個解決方案)是使用絕對導入:

from lib import b

來源: Python:導入導入模塊的模塊






Links