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/cn.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灯, 水草

请输入看板名称,例如:e-shopping站内搜寻

TOP