其實也是在寫自己項目的時候遇到的,以前也遇到了但是一直采取的是回避的策略,這次總算弄清楚所以總結一下。
這個項目的頂級目錄是medivac,他本身是一個python模塊。
熟悉flask的人都知道,在寫一個flask項目的時候,我們常常將一個模塊的app初始化放在根目錄的__init__.py文件中。
然后可以很方便的把其它需要路由的模塊都引入到這個__init__.py中達到自動加載並且路由的效果。
另外也可以使用一個叫做flask藍圖的東西(blueprint),將模塊細分。
如果是在__init__.py初始化了app(就暫時理解成app=Flask(__name__)),name在views中我們建立一個叫hello的文件,並且寫一個函數路由他像這樣
from medivac import app @app.route("/") def hello(): return "let's move!"
會爆出這樣的錯誤
from medivac import app ImportError: No module named medivac
為什么會找不到medivac模塊?我們都知道在導入該模塊下面__init__.py東西的時候直接寫該模塊名字就可以,因為__init__.py默認會運行加載。如果使用IDE會發現代碼毫無問題,也可以正常跳轉。
后來發現並不能這么寫,必須要medivac上面還有文件夾包住的時候,這樣的尋址才可以。在python看來,他看不到這個根目錄,他認為項目目錄是
medivac/ 而不是 /medivac/
所以如果改成這樣
from __init__ import app
就可以正常運行了。
但是我覺得這樣坑蠻多的,新建一個.py文件來初始化app,然后使用藍圖來路由也是不錯的選擇。
特別注意,還有一個嚴重影響模塊尋址的環境變量PYTHONPATH,將當前環境變量的PYTHONPATH設置成對應的地址,可以方便的幫助絕對尋址。
另外順便提一點,關於uwsgi的配置
[uwsgi] # uwsgi 啟動時所使用的地址與端口 socket = 127.0.0.1:8001 # 指向網站目錄 chdir = /home/medivac/project/medivac # python 程序內用以啟動的 application 變量名 module = app callable = app master = True # 處理器數 processes = 1 # 線程數 threads = 1 # 工作進程 workers = 1
當指定的chdir是/home/medivac/project/medivac的時候那么module代表的是去哪個文件里找callable 這個app來進行加載。
Reference:
http://stackoverflow.com/questions/11536764/how-to-fix-attempted-relative-import-in-non-package-even-with-init-py