设为首页 收藏本站
查看: 572|回复: 0

[经验分享] [Python源码学习]之模块路径

[复制链接]

尚未签到

发表于 2017-5-1 13:23:35 | 显示全部楼层 |阅读模式
接前面Python源码笔记之Py_InitializeEx,尝试看看Python中用到的一些Path
(这部分东西太乱了...具体见PC/getpathp.c 和 Modules/getpath.c 中的注释)。
一个Python程序要有运行,必须要能找到 .py/.pyc/.pyo/.pyd/.so 等,如何找到这些模块,还真是个问题:



sys.executable



可执行程序完整路径(其他函数可据此查找python运行时需要的库)




sys.prefix



平台无关文件



Python安装路径,用来生成标准库搜索路径




sys.exec_prefix



平台相关文件




sys.path



模块搜索路径





prefix 和 exec_prefix,平时用,几乎总是一样的,应该不用细分。





常见默认值




Unix (pure)



prefix/lib/pythonX.Y



/usr/local/lib/pythonX.Y




Unix (non-pure)



exec-prefix/lib/pythonX.Y/



/usr/local/lib/pythonX.Y




Windows



prefix\Lib



C:\PythonXY\Lib\






何处初始化?



这4个均在Py_InitializeEx进行初始化:




初始值




executable



Py_GetProgramFullPath()




prefix



Py_GetPrefix()




exec_prefix



Py_GetExecPrefix()




path



Py_GetPath()







  • _PySys_Init()



PyObject *
_PySys_Init(void)
{
    SET_SYS_FROM_STRING("executable",
                        PyUnicode_FromWideChar(
                               Py_GetProgramFullPath(), -1));
    SET_SYS_FROM_STRING("prefix",
                        PyUnicode_FromWideChar(Py_GetPrefix(), -1));
    SET_SYS_FROM_STRING("exec_prefix",
                        PyUnicode_FromWideChar(Py_GetExecPrefix(), -1));
...




  • PySys_SetPath(Py_GetPath());



void
PySys_SetPath(const wchar_t *path)
{
    PyObject *v;
    if ((v = makepathobject(path, DELIM)) == NULL)
        Py_FatalError("can't create sys.path");
    if (PySys_SetObject("path", v) != 0)
        Py_FatalError("can't assign sys.path");
    Py_DECREF(v);
}


环境变量



与这些path相关的有两个环境变量非常关键:


  • PYTHONHOME

用来指定 prefix 和 exec_prefix 的值,格式:"ThePrefixPath" 或 "ThePrefixPath:TheExec_prefixPath"。注意,指定两个路径时,用冒号分割。
如果使用Py_SetPythonHome()设置了home值,则不会使用环境变量指定的值!


  • PYTHONPATH

设置模块的默认搜索路径,路径间分隔符和平台相关:Windows下分号,其他平台冒号。


3个函数



除了前面的环境变量,下面3个函数也很重要(在Py_InitializeEx之前调用)




  • Py_SetProgramName()



  • Py_SetPythonHome()



  • Py_SetPath()


注意:使用Py_SetPath()以后,prefix和exec_prefix都将为空。Manual中说多个路径采用分号分割!这是错的,应该是和平台相关,Windows下用分号,其他平台冒号。


路径确定



大致分两步:


  • 首先确定 prefix 和 exec_prefix


  • 然后,在prefix和exec_prefix上面追加libpath(比如lib/pythonXX/)以及PYTHONPATH中指定的路径(比如在linux下,可能是L":plat-linux2")



prefix



prefix 的确定(linux下):




  • 如果PYTHONHOME被设置(无论是环境变量,还是Py_SetPythonHome()),则无条件使用它。



  • 否则,按照可执行程序所在路径(Py_SetProgramName)依次往上搜索(准则是:lib/pythonXX/os.py(os.pyc、os.pyo)文件)

  • 否则,使用configure时设置的值

Windows下,prefix和exec_prefix没多大意思了,主要就是确定Pyathon的主目录:


  • 如何PYTHONHOME被设置,则使用
  • 否则,按照可执行程序所在目录向上搜索 (lib/os.py)
  • 否则,查找注册表


path



即 sys.path 的初始值:




  • 如果使用Py_SetPath()设置了路径,则直接使用这些路径

  • 反之:按下面的规则生成

    • 首先添加:环境变量 PYTHONPATH 设置的路径
    • 其次:默认的zip文件路径(和prefix相关),比如:prefix/lib/pythonXX.zip


    • 再次:编译期设置的一些路径(通过PYTHONPATH),和prefix合并成得到的路径,比如:

      • prefix/lib/python3.2
      • prefix/lib/python3.2/plat-linux2


    • 最后:动态加载模块的路径(和exec_prefix相关),比如:exec_prefix/lib/python3.2/lib-dynload



于是,在linux下,可以见到:



'/usr/lib/python3.2'



.py/.pyc/.pyo




'/usr/lib/python3.2/plat-linux2'



平台相关的 .py/.pyc/.pyo




'/usr/lib/python3.2/lib-dynload'



动态库的 .so






参考






  • http://docs.python.org/py3k/using/cmdline.html#envvar-PYTHONHOME



  • http://docs.python.org/py3k/c-api/init.html



  • http://docs.python.org/py3k/install/index.html


运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-371660-1-1.html 上篇帖子: python访问纯真IP数据库 下篇帖子: 【记录】使用python并行执行shell
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表