2012-08-15 47 views
2

Python導入。再次...導入錯誤 - 發生了什麼?

我有這個文件的結構:

[test] 
    start.py (from scripts import main) 
    [scripts] 
     __init__.py (empty) 
     main.py (from . import install) 
     install.py (from scripts import main # or # from . import main) 

我得到導入錯誤:

[email protected]:~/projects/test$ python3 start.py 
Traceback (most recent call last): 
    File "start.py", line 2, in <module> 
    from scripts import main 
    File "/home/vic/projects/test/scripts/main.py", line 1, in <module> 
    from . import install 
    File "/home/vic/projects/test/scripts/install.py", line 1, in <module> 
    from scripts import main 
ImportError: cannot import name main 
[email protected]:~/projects/test$ 

我不明白:第一次from scripts import main工作(通過 「合作」 我的意思是它沒有與ImportError失敗),第二次相同的代碼給出ImportError: cannot import name main

這是怎麼回事?

更新:

我的問題不是關於循環進口。我很困惑的事實,即完全相同的代碼from scripts import main第一次工作正常,然後第二次失敗。

我想有一些內部導入機制,我不明白。

第一次語句導入模塊,第二次完全相同的代碼嘗試從模塊導入名稱。這是如何工作的?

+0

我不是這個話題的專家,這是少了很好的答案,但這[鏈接](http://docs.python.org/dev/howto/pyporting.html#from-future-import-absolute-import)可能會幫助你。 – sfx 2012-08-15 17:59:27

回答

5

您創建了一個循環導入。你不能那樣做。避免從install導入main

發生了什麼事情是一個模塊在導入時,在整個頂層被執行之前是不完整的。如果在執行期間它導入另一個模塊(直接或間接)嘗試再次導入原始模塊,則這將失敗。原始模塊尚未完成導入。

換句話說,你要創建一個圓形圖:

start -> scripts.main -> scripts.install 
      ^    | 
       |    | 
       ---------------- 

您需要重新安排你的代碼,不需要從mainscripts包中導入。

請參閱What are the 「best practices」 for using import in a module?瞭解如何處理此問題的一些提示。

+0

我希望第二次像第一次那樣工作,即導入'scripts.main'並將其分配給名稱'main' – warvariuc 2012-08-15 17:54:48

+0

>原始模塊還沒有導入。<然而,它已經在'sys.modules',儘管它的導入沒有完成 – warvariuc 2012-08-15 17:56:52

+0

是的,但它是*不完整*。 Python不能保證你試圖導入的對象實際上會在那裏或正確定義。 – 2012-08-15 17:58:56

0

這應該工作:

start.py:

from scripts import main 

腳本/ main.py:

import install 

腳本/安裝。潘岳:

import main 
+0

這與我的情況不同。我嘗試從一個包中導入一個模塊,而不是從另一個模塊的名稱 – warvariuc 2012-08-15 18:06:43

+0

已更新的答案以解決您的問題 – Arseniy 2012-08-16 06:11:52

3

main進口installinstall進口main

  • start.pyfrom scripts import main導致
  • from . import installmain.py導致
  • from scripts import maininstall.py - 圓形進口

要解決循環導入要麼將maininstall合併到單個模塊中,要麼創建兩個模塊都可以導入的第3個模塊。

+0

請參閱我的更新 – warvariuc 2012-08-15 18:18:04

+0

@warwaruk:我已經明確說明了該序列。 '從腳本導入main' *不會*第一次工作,因爲它從來沒有完成首先。 – jfs 2012-08-15 18:28:19

0

這是一個補丁我用它來覆蓋默認行爲:

import sys 
import builtins 
import importlib 

def _import(name, globals=None, locals=None, fromlist=None, level=0, __import__=__import__): 
    """A hack to to make names of imported modules to be available in the parent package before 
    they are fully imported. If a module is present in sys.modules event if it's not fully 
    imported, it should not be a problem. 
    I.e. ``from package import module1, module2`` will create variables ``package.module1`` and 
    ``package.module2`` at start of the import, not when it's finished. 
    This helps in some situations with circular import. 
    """ 
    module = __import__(name, globals, locals, fromlist, level) 
    for attr in fromlist or(): 
     sub_module = sys.modules.get(module.__name__ + '.' + attr) 
     if sub_module: # is this a module? 
      # if subpackage is already being imported, even if not finished, 
      # inject its name into the parent package 
      setattr(module, attr, sub_module) 
    return module 

builtins.__import__ = _import 

這裏是測試這個項目:https://github.com/warvariuc/python_import_improver