→ uranusjr: Absolute import 那邊不太對, 它只看 sys.path, 不一定 06/22 19:25
→ uranusjr: 是先找 built-in (其實 Python 直譯器本身並不知道哪些 06/22 19:26
→ uranusjr: 模組是 built-in 哪些不是) 06/22 19:26
→ uranusjr: 不過這篇的概念很棒, 可惜我不是板主不能 m... 06/22 19:28
→ ThxThx: 我猜這裡的built in是指用C寫的那些modules,不過從來沒試 06/22 23:31
→ ThxThx: 過XD。 06/22 23:31
推 os653: 想請教一下,那 debug 跟 test 的檔案要放哪裡? 06/23 08:45
→ os653: 按照此篇所述,debug 跟 test 的檔案要放在 project 最上層 06/23 08:45
→ os653: 如此才能不加工 sys.path 又能使用 relative import 06/23 08:46
sys.path和relative import無關
→ os653: 但這很奇怪呀,尤其 test 還有可能依測試目的放不同資料夾 06/23 08:47
我修改了上面project的架構,test資料夾通常會放在top-level。
我假設你說的debug是指開發的時候用來測的script,test是指拿來跑unit test的檔案。
Debug我會把他看成是用完就丟不會把他放進版控,所以不是放在最上層就是加`sys.path`
,不然就是用`PYTHONPATH`
test的話有蠻多種的,我是用pytest這個framework,然後執行的時候加`PYTHONPATH`
,像是
PYTHONPATH='./' pytest
另外,如果你寫好setup.py,那可以用tox這個工具幫你創好虛擬環境(而且一次跑多個
版本的python),安裝你寫的package然後跑你要的指令。所以open source常見的組
合就是
tox(創環境) + pytest(找test script來跑) + travis(免洗的標準環境)
當然小project可以不用這麼認真,原則就是自動化test,source code不要亂加東西。
最後請注意,以上講的都是用absolute import。Relative import是在你寫的package裡面
用,absolute import是用來找到package的root folder。
※ 編輯: ThxThx (114.44.244.29), 06/23/2018 11:39:54
推 os653: 感謝解說,有空試試看這篇裡講的東西看看會不會比較好用 06/23 15:41
推 clsmbstu: 感謝解說!有幾個問題我想再請教一下: 06/24 14:30
→ clsmbstu: 1. PYTHONPATH環境變數可以賦予數個不同的資料夾嗎? 06/24 14:31
就跟你設PATH一樣用冒號隔開
→ clsmbstu: 2. 如果我沒理解錯,看起來relative import只能寫在「會 06/24 14:33
→ clsmbstu: 被其它script/module import的module」?在程式本身寫 06/24 14:34
→ clsmbstu: relative import的話,一定會因為碰到__main__而錯誤。 06/24 14:34
不像javascript,code愛放哪就放哪
import python module要先找到package(用absolute import)然後再用點(dot)往下鑽
relative import是給你在自己的package底下互相引用用的
→ clsmbstu: BTW 對我來說 最常碰到的困擾倒不是因為debug或test檔案 06/24 14:41
→ clsmbstu: 我在做的大多是data analyses,所以本來就會把檔案歸類 06/24 14:45
→ clsmbstu: 成不同的資料夾,例如: 06/24 14:45
→ clsmbstu: projects/crons/month 是產生資料月報有關的檔案 06/24 14:47
→ clsmbstu: projects/crons/week 是產生資料週報有關的檔案 06/24 14:47
→ clsmbstu: projects/prediction_model 跟公司業務預測模型有關 06/24 14:48
→ clsmbstu: projects/connection 連接公司資料庫所需的package 06/24 14:49
→ clsmbstu: projects/utils 是資料前處理、資料清洗的package 06/24 14:50
→ clsmbstu: 這種狀況下,relative import卻完全幫不上忙 @@ 06/24 14:51
→ clsmbstu: 又要不修改sys.path的話,只能讓PYTHONPATH指向多處? 06/24 14:52
設PYTHONPATH是在執行的時候修改sys.path啊:P
如果是這樣,那還不如加在sys.path裡面,至少不用記得執行的時候要加東西。
你會這樣放code可能也有其他的考量,我會這樣建議是覺得,隨意加sys.path也許沒有增
加現在的開發成本,但是絕對是增加維護的成本。哪個成本比較重要就要看你的選擇了。
回過頭來,現在假設問題就是crons/week和prediction_model裡的scripts都需要utils的
package。以前可能是每個script都寫很長,但現在如果變成
projects/
crons_week.py
crons_month.py (scripts)
predict.py
...
crons/
... (產生資料報表的功能)
prediction_model/
... (model本身)
utils/
... (其他共用的邏輯)
所有第一層scripts的功能是parse CLI arguments然後呼叫其他資料夾裡面的功能,不要
把複雜的邏輯寫在這裡面。也許這樣每個人就很容易了解這些檔案在做什麼、每個package
各自擁有什麼功能。
所以就是,我主張每個package把他看成是功能的集合/公約數。不一定要照做,不過
至少你現在知道absolute/relative import的原理了XD
→ clsmbstu: 這也是為什麼我第一個問題那麼問 06/24 14:53
※ 編輯: ThxThx (114.44.244.29), 06/25/2018 01:27:26
推 clsmbstu: Thank you!!! 06/25 10:29