想象一下這個目錄結構: python
app/ __init__.py sub1/ __init__.py mod1.py sub2/ __init__.py mod2.py
我正在編碼mod1
,我須要從mod2
導入一些東西。 我該怎麼辦? app
我嘗試from ..sub2 import mod2
嘗試from ..sub2 import mod2
但出現「未打包的相對嘗試導入」。 測試
我四處搜尋,但只發現「 sys.path
操縱」黑客。 有沒有一種乾淨的方法? 編碼
編輯:我全部的__init__.py
當前爲空 spa
Edit2:我正在嘗試執行此操做,由於sub2包含跨子包( sub1
, subX
等)共享的類。 code
Edit3:我要尋找的行爲與PEP 366中描述的相同(感謝John B) ip
def import_path(fullpath): """ Import a file with full path specification. Allows one to import from anywhere, something __import__ does not do. """ path, filename = os.path.split(fullpath) filename, ext = os.path.splitext(filename) sys.path.append(path) module = __import__(filename) reload(module) # Might be out of date del sys.path[-1] return module
我正在使用此代碼片斷從路徑導入模塊,但願對您有所幫助 ci
除了John B所說的之外,設置__package__
變量彷佛應該有所幫助,而不是更改__main__
可能會搞砸其餘事情。 可是據我測試,它並不能徹底正常工做。 字符串
我遇到了一樣的問題,而據我所知,PEP 328或366都沒法徹底解決問題,由於二者在一天結束時都須要將程序包的頭包含在sys.path
。 get
我還要提到的是,我沒有找到如何格式化應放入這些變量的字符串的格式。 是"package_head.subfolder.module_name"
仍是什麼?
讓我將其放在此處以供我本身參考。 我知道這不是很好的Python代碼,可是我須要一個腳原本處理我正在從事的項目,因此我想將該腳本放在scripts
目錄中。
import os.path import sys sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
這是對我有效的解決方案:
我from ..sub2 import mod2
進行相對from ..sub2 import mod2
,而後,若是我想運行mod1.py
則轉到app
的父目錄,並使用python -m開關做爲python -m app.sub1.mod1
運行模塊python -m app.sub1.mod1
相對導入發生此問題的真正緣由是,相對導入經過採用模塊的__name__
屬性__name__
。 若是模塊直接運行,則__name__
設置爲__main__
,而且不包含有關包結構的任何信息。 而且,這就是爲何python抱怨relative import in non-package
錯誤中的relative import in non-package
。
所以,經過使用-m開關,您能夠將包結構信息提供給python,經過它能夠成功解析相對導入。
在進行相對導入時,我屢次遇到此問題。 並且,在閱讀了全部先前的答案以後,我仍然沒法弄清楚如何解決此問題,而無需在全部文件中都放入樣板代碼。 (儘管有些評論確實頗有幫助,這要感謝@ncoghlan和@XiongChiamiov)
但願這對正在解決相對進口問題的人有所幫助,由於經過PEP確實頗有趣。
用示例解釋nosklo's
答案
注意:全部__init__.py
文件均爲空。
main.py app/ -> __init__.py package_a/ -> __init__.py fun_a.py package_b/ -> __init__.py fun_b.py
def print_a(): print 'This is a function in dir package_a'
from app.package_a.fun_a import print_a def print_b(): print 'This is a function in dir package_b' print 'going to call a function in dir package_a' print '-'*30 print_a()
from app.package_b import fun_b fun_b.print_b()
若是運行$ python main.py
它將返回:
This is a function in dir package_b going to call a function in dir package_a ------------------------------ This is a function in dir package_a
from app.package_b import fun_b
from app.package_a.fun_a import print_a
所以,文件夾package_b
中的文件使用了文件夾package_a
中的文件,這就是您想要的。 對??