pythonimport踩坑指南sys.path失效解决⽅案
不关⼼故事背景的朋友们可以直接跳到“解决⽅案”~
⽂章⽬录
故事背景
最近在⽤thrift的时候遇到⼀个问题,thrift⽣成的python⽂件之间的引⽤都是相对引⽤的:
thrift_folder
├── base
│├── constants.py
│├── __init__.py
│└── ttypes.py
├── model
│├── __init__.py
│├── constants.py
│├── ttypes.py
# model/ttypes.py
pes
如果python起始运⾏⽂件路径不在thrift_folder内,那么引⽤就会有错误。
历史⽅案
⽼前辈们提供了两种解决⽅案
修改所有的import
修改os.path
前者的问题在于,即使⽤脚本在每个thrift前⾯写from thrift_folder import base(不能图省事先加⼀个_
_all__ = bulabula然后from thrift_folder import *,这样可能会循环引⽤),在thrift⽂件⾥⾯还是会藏着很多pes.XXX的⿁东西,需要⼀个个改……第⼀位⽼前辈就⼀个个改完了。当然可能他的thrift很少,我现在看着⼏⼗万⾏的thrift真的改不了= =
后者的问题在于os.path可能失效,这是为啥呢,请看下⽂分解——
解决⽅案
坑1:sys.path不能⽤append
在查modules的位置时,python按照sys.path顺次查询,如果你⽤了append,很可能引⽤到了其他的模块。那么解决⽅案是
sys.path.insert(0,thrift_folder)
坑2:dules缓存路径(insert0还是不⾏啊喂)
python在import module前,先会去dules看看曾经有没有导⼊过这个模块,这是⼀个类似于modules path cache的地⽅。模块在dules中不代表当前⽂件能调⽤它(可能是其他⽂件的代码中import了,然后把dules更新了);但是调⽤新模块的时候会优先查dules有没有,
有的话就不管sys.path了,直接从这⾥导⼊… 【想了好久也没懂这个机制可能快⼀丢丢之外有什么⽤途】
于是需要查看⼀下dules有没有曾经导⼊模块留下的痕迹,如果有的话需要把它们都解决掉,这样就可以正常引⽤啦~ 当然,成功导⼊thrift之后别忘记把原来的dules/sys.path还原。
# 如果在该模块导⼊之前有过import lv_thrift下的⼦模块同名模块,会导致从# dules中加载路径,所以同时对dules进⾏修改
import_modules =['base','model'...]
import_modules +=[s+'.ttypes'for s in import_modules]
sys_modules_backup =dict()
for mod in import_modules:
dules.has_key(mod):
thriftsys_modules_backup[mod]= dules[mod]
dules[mod]
full_path = alpath(__file__)
thrift_path = os.path.join(os.path.dirname(full_path),"thrift_folder")
sys.path.insert(0,thrift_path)
# import thrift
from base import xxx
from model import yyy
pes import zzz
...
# 恢复sys.path & dules
ve(thrift_path)
for mod,path in sys_modules_backup.items():
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论