1. 程式人生 > >ImportError: No module named 'xxx'的另外一種原因

ImportError: No module named 'xxx'的另外一種原因

今天遇到了一個關於Python的ImportError: No module named 'xxx'問題,其中也算是一些經驗總結,特記錄如下。

    問題的場景大致是這樣的:在django中我新建了一個名為sitesetting的app,這個app不是通過django的python manage.py startapp sitesetting命令來新建的,而是我手動mkdir sitesetting命令新建的。然後用nginx+uwsgi啟動,訪問sitesetting這個app就會出現出現出現ImportError: No module named 'sitesetting'的錯誤。
    看到這個錯誤首先想到的是sitesetting目錄下面沒有_init_

.py檔案,看了一下sitesetting卻是有_init_.py檔案的。
    接著我又檢查了一下pythonpath中是包含了django的主目錄的,也就是說Python的查詢路徑是沒有問題的。
    此時我就有點納悶了,我又對照了一遍sitesetting目錄下面的檔案列表和其它正常的app的檔案列表,沒有發現問題。檢查了一下settings.py中的配置都沒有發現問題。
    接著我用python manage.py runserver 0:8080方式起來了一個服務,竟然沒有出現ImportError的錯誤,此時頭腦已經有點迷糊了,沒有去深思這個現象。
    我想要不用python manage.py startapp sitesetting
命令來新建這個app看看會不會報錯吧,mv sitesetting sitesetting2重新命名了sitesetting app,用python manage.py startapp sitesetting命令新建了sitesetting app。接著把nginx重啟一下,發現沒有報錯了。難道startapp這種方式會在某一個地方增加一些配置?我查了一遍django的文件,沒有發現startapp這種方式有什麼隱藏的功能除了新建目錄和檔案外。想哭……
    到現在能驗證的步驟基本都驗證完了,腦子也越來越迷糊了。不行,我得休息休息一會了。
    喝杯水,把整個驗證過程在腦子中過了一遍,發現有兩個驗證方法沒有報錯,這兩個都沒有什麼特別的聯絡。此時,突然腦子突然靈光一現,難道是許可權的問題?想到這一點線索,再結合這兩個沒有報錯的方式我基本就斷定了應該是許可權導致了這個”詭異”的問題。
    我ls -l
對比看了一下sitesetting(用startapp新建的)和sitesetting2(用mkdir新建的),發現一個owner:group是apache,一個是root,而且sitesetting2的許可權是700,所以用nginx+uwsgi啟動服務的時候apache使用者是沒有讀許可權的,所以最後也就報出了ImportError的錯誤。

drwxr-xr-x 2 apache apache 4.0K May 18 17:09 sitesetting

drwx------ 2 root   root   4.0K May 18 15:37 sitesetting2

    折騰了半天最後發現是這麼一個原因導致的問題,事後回想了一下其實我很早以前也遇到過類似的問題,用manage.py的方式沒有問題,用nginx+uwsgi就有問題,當時也是折騰了半天才發現原因。這次我總結了幾點:
1. 凡是遇到manage.pynginx+uwsgi執行不一致的情況,一定要優先考慮許可權的問題。
2. 測試的時候不要認為manage.py自測沒問題了就OK了,一定要模擬真正的線上環境來測試。
3. Python的ImportError除了前面我們列舉的幾個可能原因以外再加一個py檔案許可權的原因。
4. 遇到這種百思不得其解的問題一定不要鑽牛角尖,適當的放鬆思考。