Python 板


LINE

原諒我只回關於import的部份XD。這部份我發現第一次遇到很難搞懂又常常忘記,我自己 也是邊查邊寫。 import 的邏輯是什麼!? ====================== 這邊比較能夠細讀的官方文件是PEP-328和 https://docs.python.org/3/tutorial/modules.html 。 ## Absolute Import Absolute import 非常簡單,只要不是以點(dot)開頭的就是absolute import,例如: import foo import foo.bar as bar from foo import bar Absolute import的邏輯就是先找built-in module,沒有的話從`sys.path`的資料夾底下 找一個<name>.py的檔案或是<name>的package(package的定義:帶有`__init__.py`)。 `sys.path`的組成包含 * 程式進入的script的資料夾 * `PYTHONPATH`環境變數 * 安裝python時指定的位置,通常是放安裝的檔案 ## Relative Import Relative import 以點作為起始,兩個點代表上一層,以此類推,而且永遠都是用 `from <> import <>` 來敘述。 至於這個"relative"是相對什麼?這個是用當前module的`__name__`來決定 * 如果它是`foo.bar`之類的值,那就是從`foo.bar`來做相對移動。 `foo`就是最上層的module。 * 如果它是`__main__`(當你執行python script的進入點), 那這個script就是最上層的module。 最後,不管是那一種relative import,都不能超過最上層的module。 ## Import, the Pythonic Way 首先是,不要使用`from foo import *`這種形式。python的名字是會被覆蓋的,也就是 說如果連續兩行 `from <name> import *`然後又有重複的名字,那就會被第二行覆蓋。 然後,分開程式進入點的檔案(`__name__`是`__main__`)還有package。理由是你的進 入點會變成是`__main__`,那就沒辦法用relative import,那你就只能仰賴`sys.path` 來找你自己開發的檔案。如果你不想要自己加工`sys.path`,那就要把你的package放在 程式進入點那層,也就是這樣 project/ main.py setup.py packageA/ ... tests/ funtionA/ test_XXX.py ... ... 最後,盡量不要加工`sys.path`。原因跟第一點一樣是名稱衝突的問題:module是依序在 `sys.path`裡面找,加工會影響其他module,可能會讓後來的module import到錯的檔案, 這種超級難debug。 ## Take Away * absolute import: 用`sys.path`決定 * relative import: 用`__name__`決定,不能超過top-level module * 不要用`*`、分開entrypoint和package、不要加工`sys.path` --



※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 114.44.244.29
※ 文章網址: https://webptt.com/m.aspx?n=bbs/Python/M.1529654464.A.920.html
1F:→ uranusjr: Absolute import 那邊不太對, 它只看 sys.path, 不一定 06/22 19:25
2F:→ uranusjr: 是先找 built-in (其實 Python 直譯器本身並不知道哪些 06/22 19:26
3F:→ uranusjr: 模組是 built-in 哪些不是) 06/22 19:26
4F:→ uranusjr: 不過這篇的概念很棒, 可惜我不是板主不能 m... 06/22 19:28
5F:→ ThxThx: 嗯!?那部份我是從https://tinyurl.com/qaasj5n 翻譯來 06/22 23:31
6F:→ ThxThx: 我猜這裡的built in是指用C寫的那些modules,不過從來沒試 06/22 23:31
7F:→ ThxThx: 過XD。 06/22 23:31
8F:推 os653: 想請教一下,那 debug 跟 test 的檔案要放哪裡? 06/23 08:45
9F:→ os653: 按照此篇所述,debug 跟 test 的檔案要放在 project 最上層 06/23 08:45
10F:→ os653: 如此才能不加工 sys.path 又能使用 relative import 06/23 08:46
sys.path和relative import無關
11F:→ 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
12F:推 os653: 感謝解說,有空試試看這篇裡講的東西看看會不會比較好用 06/23 15:41
13F:推 clsmbstu: 感謝解說!有幾個問題我想再請教一下: 06/24 14:30
14F:→ clsmbstu: 1. PYTHONPATH環境變數可以賦予數個不同的資料夾嗎? 06/24 14:31
就跟你設PATH一樣用冒號隔開
15F:→ clsmbstu: 2. 如果我沒理解錯,看起來relative import只能寫在「會 06/24 14:33
16F:→ clsmbstu: 被其它script/module import的module」?在程式本身寫 06/24 14:34
17F:→ clsmbstu: relative import的話,一定會因為碰到__main__而錯誤。 06/24 14:34
不像javascript,code愛放哪就放哪 import python module要先找到package(用absolute import)然後再用點(dot)往下鑽 relative import是給你在自己的package底下互相引用用的
18F:→ clsmbstu: BTW 對我來說 最常碰到的困擾倒不是因為debug或test檔案 06/24 14:41
19F:→ clsmbstu: 我在做的大多是data analyses,所以本來就會把檔案歸類 06/24 14:45
20F:→ clsmbstu: 成不同的資料夾,例如: 06/24 14:45
21F:→ clsmbstu: projects/crons/month 是產生資料月報有關的檔案 06/24 14:47
22F:→ clsmbstu: projects/crons/week 是產生資料週報有關的檔案 06/24 14:47
23F:→ clsmbstu: projects/prediction_model 跟公司業務預測模型有關 06/24 14:48
24F:→ clsmbstu: projects/connection 連接公司資料庫所需的package 06/24 14:49
25F:→ clsmbstu: projects/utils 是資料前處理、資料清洗的package 06/24 14:50
26F:→ clsmbstu: 這種狀況下,relative import卻完全幫不上忙 @@ 06/24 14:51
27F:→ 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
28F:→ clsmbstu: 這也是為什麼我第一個問題那麼問 06/24 14:53
※ 編輯: ThxThx (114.44.244.29), 06/25/2018 01:27:26
29F:推 clsmbstu: Thank you!!! 06/25 10:29







like.gif 您可能會有興趣的文章
icon.png[問題/行為] 貓晚上進房間會不會有憋尿問題
icon.pngRe: [閒聊] 選了錯誤的女孩成為魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一張
icon.png[心得] EMS高領長版毛衣.墨小樓MC1002
icon.png[分享] 丹龍隔熱紙GE55+33+22
icon.png[問題] 清洗洗衣機
icon.png[尋物] 窗台下的空間
icon.png[閒聊] 双極の女神1 木魔爵
icon.png[售車] 新竹 1997 march 1297cc 白色 四門
icon.png[討論] 能從照片感受到攝影者心情嗎
icon.png[狂賀] 賀賀賀賀 賀!島村卯月!總選舉NO.1
icon.png[難過] 羨慕白皮膚的女生
icon.png閱讀文章
icon.png[黑特]
icon.png[問題] SBK S1安裝於安全帽位置
icon.png[分享] 舊woo100絕版開箱!!
icon.pngRe: [無言] 關於小包衛生紙
icon.png[開箱] E5-2683V3 RX480Strix 快睿C1 簡單測試
icon.png[心得] 蒼の海賊龍 地獄 執行者16PT
icon.png[售車] 1999年Virage iO 1.8EXi
icon.png[心得] 挑戰33 LV10 獅子座pt solo
icon.png[閒聊] 手把手教你不被桶之新手主購教學
icon.png[分享] Civic Type R 量產版官方照無預警流出
icon.png[售車] Golf 4 2.0 銀色 自排
icon.png[出售] Graco提籃汽座(有底座)2000元誠可議
icon.png[問題] 請問補牙材質掉了還能再補嗎?(台中半年內
icon.png[問題] 44th 單曲 生寫竟然都給重複的啊啊!
icon.png[心得] 華南紅卡/icash 核卡
icon.png[問題] 拔牙矯正這樣正常嗎
icon.png[贈送] 老莫高業 初業 102年版
icon.png[情報] 三大行動支付 本季掀戰火
icon.png[寶寶] 博客來Amos水蠟筆5/1特價五折
icon.pngRe: [心得] 新鮮人一些面試分享
icon.png[心得] 蒼の海賊龍 地獄 麒麟25PT
icon.pngRe: [閒聊] (君の名は。雷慎入) 君名二創漫畫翻譯
icon.pngRe: [閒聊] OGN中場影片:失蹤人口局 (英文字幕)
icon.png[問題] 台灣大哥大4G訊號差
icon.png[出售] [全國]全新千尋侘草LED燈, 水草

請輸入看板名稱,例如:Tech_Job站內搜尋

TOP