Python2.7直接运行包内app.py时如何触发对应__init__.py执行
基础环境信息
- 测试目录结构
-- tst ------ __init__.py ------ app.py
- 执行命令:
python27 app.py - 预设条件:
tst/__init__.py中预置了其他导入语句,本示例中内容为import os
问题解答
直接执行app.py时如何触发对应包的__init__.py运行
直接进入tst目录执行python27 app.py时,Python会将脚本所在的tst目录加入sys.path搜索路径头部,同时将app.py标记为__main__主模块,此时Python不会认为app.py从属于tst包,默认不会自动执行上层tst包的__init__.py。
理论层面要触发__init__.py执行,核心是让Python识别到app.py是tst包的组成部分:
- 最贴合Python导入机制的方式是退到
tst目录的父级路径,用模块模式启动:python27 -m tst.app。这种启动方式下Python会先识别tst为合法包,自动执行tst/__init__.py的全部逻辑,再运行app.py中的代码。 - 如果必须直接执行
app.py文件路径,需要在app.py最开头手动修改sys.path,将tst的父级目录加到搜索路径优先级最高的位置,再显式导入tst包,但这种方式会碰到同名模块歧义问题。
存在多个同名tst模块时,直接写import tst是否会有导入歧义
一定会产生导入歧义。Python的模块搜索严格按照sys.path的顺序从前到后匹配,直接执行app.py时,搜索路径第一个条目是app.py所在的tst目录,这个路径下本身不存在名为tst的子模块/子包,Python会继续往后遍历搜索路径,第一个匹配到的tst模块就会被加载,完全可能导入到其他路径下的同名tst包,不会自动定位到当前app.py所属的tst包。
是否存在import .这类写法触发父包__init__.py执行
Python2.7中完全不支持这类写法,原因有两个:
- 所有带
.的相对导入,只有当模块被作为包的成员加载(也就是__package__属性有对应包名)时才能生效。直接把app.py作为主脚本运行时,它的__package__值为None,任何相对导入都会直接抛出"非包内尝试相对导入"的错误。 - 哪怕是在包内模块正常被导入的场景下,
import .本身也是非法语法。Python的相对导入规则要求,import语句后必须跟明确的模块名,相对导入场景下可以写from . import some_module,但不允许直接用点号指代当前包/父包完成导入,自然也没法通过这种写法触发__init__.py执行。
注:以上为Python2.7导入机制的理论层面探讨,实际开发中遵循规范的包导入、模块启动方式即可规避这类问题。
内容的提问来源于stack exchange,提问作者Nicholas Kunes
相关产品推荐
相关产品推荐

