标签 site.py 下的文章

Python内置子模块之site.py

为什么要做

这里主要以python2.7版本代码为例,用来进行自动的预配置第三方模块目录。 如果你在系统中安装了Django,python需要知道如何才能找到Django模块,这个时候site.py就起预配置的作用。

官方文档
源代码

做了什么

python本身导入模块是以sys.path为依据的,调用imp模块来进行导入。

sys.path初始化分两步:

  • 第一步,python进程本身,是由getpathp.c实现的,加入python本身导入路径。
  • 第二步,调用site.py附加一些第三方部模块导入路径。

所以site.py的本质就是补充sys.path路径,协助python预配置第三方模块目录。

什么特点

  • 补充sys.path路径,协助python预加载第三方模块

允许通过-S/-s 参数和 _PYTHONNOSITEPACKAGES等环境变量进行开关

  • 允许通过调用addsitedir,进行程序级别扩充sys.path 。

不推荐直接修改sys.path,会丢失一部分特性。

  • 支持.pth扩展文件(只对sys.path目录起效),允许继续追加sys.path。

同时python进行.pth解析中,允许直接进行代码执行 (后门有木有,python进程插入)

  • 支持用户自定义第三方模块,权限细化隔离。

应用场景

  • import 的时候得到包含第三方模块路径的sys.path
  • 协助确认系统是否已经安装指定包,比如setuptools,pip等 (其实只是给出目录)。
  • virtualenv patch 这个模块实现目录级别的包管理。
  • 需要扩充sys.path时,更推荐调用 site.addsitedir方法。
  • 利用.pth文件的支持,代替PYTHONPATH,实现系统和程序的隔离。

踩过的坑

  • 导入顺序和系统模块覆盖问题。

在项目根目录自己写了一个site.py 然后从这里启动django。 结果一直提示找不到django,各种重装,各种版本尝试,始终找不到django。 删掉新写的site.py 就好了why?, 因为sys.path第一个变量一般是本地执行目录,所以优先导入本地的site.py代替系统的site导入第三方模块功能就没了。 (同样该问题使用在其他内置模块,比如命名一个re.py,原始的re就功能丢失了)

解决方法 1.不与系统原有模块名称冲突,2.采用绝对导入PEP328

  • 不同版本同名模块,版本判断问题。

系统里同时存在两个版本django (别管怎么装,都是泪啊) 比如一个1.3 一个1.6 当安装系统库依赖 django >=1.5版本时,问题就出来了,到底需不需要更新? site.py提供功能太原始了。给个目录其他直接想办法,遇到用os.listdir的还要看人品。

解决方法 1.统一安装途径。 这样入口可以管控起来。(推荐都用pip) 2.权限隔离,少数人有root权限,平时降权操作。