• Python多个项目多个虚拟环境同时调用自己写的工具函数


    1.软件环境⚙️

    Windows10 教育版64位
    Python 3.6.3
    Pycharm 2020.1

    2.问题描述🔍

    相信各位在多年写代码的过程中,肯定都会结合自己所学的专业和项目总结出许多量身定制的常用工具函数。比如这些函数可以快速对图像进行预处理,有的可以把任意格式的时间转成标准格式,还有的可以自动生成正则表达式
    往往我们会把这些工具函数分别放到多个.py文件,然后把这些.py文件放在一个叫做utils的文件夹中。这样的话,如果有项目需要使用工具函数中的功能就可以直接调用,而不用重复造相同功能的轮子了!
    当我们在其他项目中import utils时,由于utils文件夹和我们的项目文件夹(图中黄色方框)是同级的:

    在这里插入图片描述

    例如我这边有2个项目online learningproblematic_map_server_code,这2个项目下面的video_atlas_online_learning.py编译为pyc.py都需要调用utils文件夹下面的工具函数create_symlink.py,这时你直接在video_atlas_online_learning.py编译为pyc.py中的任意一个文件中from utils import create_symlink都会报错:

    ModuleNotFoundError: No module named 'utils'

    即:

    
    >>> from utils import create_symlink
    Traceback (most recent call last):
      File "", line 1, in <module>
      File "C:\Program Files\JetBrains\PyCharm 2020.1\plugins\python\helpers\pydev\_pydev_bundle\pydev_import_hook.py", line 21, in do_import
        module = self._system_import(name, *args, **kwargs)
    ModuleNotFoundError: No module named 'utils'
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    注意:如果正在运行的.py文件和utils是一个层级下的话,是可以成功导入的。

    一个笨的办法就是把utils函数复制到每个项目中,但这明显太低效了!
    再联想一下我们一般通过pip install xxx安装的库,都可以直接在项目中使用import语句直接调用,但这种方式要么需要把代码上传到 Pypi 或者 Github自己编译安装到虚拟环境中,这种方式以及直接把工具函数复制到项目中有以下非常明显的缺点:

    1. 代码传到 Pypi 有一大堆流程有需要走,非常麻烦;
    2. 如果你有多个虚拟环境,那么其实每个虚拟环境都需要pip安装一遍, 其实相当于你把你的工具函数每个环境复制了一次,会形成大量的重复代码,浪费许多空间;
    3. 如果工具函数有修改,那么多个虚拟环境的都需要修改,相当于维护了多个不同环境的工具函数,异常消耗精力;

    那么,有没有什么办法,能让新起的项目直接就能导入这些自己写的工具函数呢?就像导入官方模块import math一样,不需要安装也不需要复制工具函数到每个项目中,我只需要import utils就可以了。

    在这里插入图片描述

    3.解决方法🐡

    首先,我们知道Python搜索模块的路径(即sys.path)由如下几部分组成:

    1. 程序的主目录
    2. PYTHONPATH目录
    3. 标准连接库目录
    4. 任何的.pth文件的内容,允许用户任何函数的目录添加到模块搜索路径中

    因此,根据上面的提示,有如下方法实现只需要维护1工具函数,无论这个工具函数在哪里,只要和你的项目在一台电脑上,就可以在任何项目,任何虚拟环境中直接导入我们自己写的工具函数
    我这边以编译为pyc.py这个文件为例:

    from utils import create_symlink
    
    • 1

    分别验证下述方法,如果运行编译为pyc.py不报错,证明import成功。
    utils绝对路径E:\Code\Python\utils

    3.1sys.path.append实现项目直接调用工具函数

    直接手动在代码里面,通过sys.path添加工具函数文件夹的父文件夹:

    import sys
    sys.path.append(r'E:\Code\Python')
    
    • 1
    • 2

    运行编译为pyc.py,没有报错,证明导入成功,方法可行!
    更新:其实不用每个文件都加,可以在Settings-Build,Execution,Deployment-Console-Python Console下的Starting script直接添加工具函数文件夹的父文件夹:
    在这里插入图片描述

    3.2site-packages文件夹添加.pth文件,实现项目直接调用工具函数

    相信很多同学都知道,任何放到site-packages文件夹里面的.py文件或者文件夹,都可以在 Python 中直接导入,我们通过pip install xxx安装的库也是放到这里面。
    肯定有同学要问,那是不是把utils文件夹整个复制到site-packages文件夹中呢?
    当然不是!因为utils文件夹里面的工具函数代码是在持续演进的,经常会更新里面的代码,如果只是单单放到site-packages里面以后,代码修改起来很不方便。而且,这和直接把utils文件夹复制到项目文件夹中其实根本没有什么区别!
    我们要用到的,是Python.pth文件,它可以告诉程序自动添加.pth文件中的路径作为环境变量,然后我们就可以直接导入utils中的函数了:

    3.2.1找到site-packages文件夹的路径

    直接在你的Python Console或者新建一个.py文件中输入如下代码,查询site-packages文件夹的路径:

    >>> import sysconfig
    >>> print(sysconfig.get_path('purelib'))
    C:\Users\Jayce\Anaconda3\envs\tf2.5\Lib\site-packages
    
    • 1
    • 2
    • 3

    3.2.2在site-packages文件夹中创建.pth文件

    site-packages文件夹中,任意文件名创建一个.pth文件,只要不跟已有的模块冲突就行。例如叫做pth_test.pth,然后用任意文本编辑器在其中添加工具函数的父路径即可!例如,本文中就是utils父文件夹绝对路径E:\Code\Python
    在这里插入图片描述
    运行编译为pyc.py,没有报错,证明导入成功,方法可行!

    3.2.3通过对.pth文件创建软连接,实现多个虚拟环境共用一份工具函数

    为了在多个虚拟环境中只调用1份工具函数,我们需要在我们的虚拟环境中对上述创建的pth_test.pth生成软连接,这样的话,以后即使工具函数的路径发生了变化,我们只需要修改pth_test.pth中工具函数的路径即可,不同虚拟环境中的软连接会自动应用更改。
    例如,我这边在虚拟环境:tf2.5中生成对虚拟环境:tf2.3中的pth_test.pth的软连接:

    import os
    
    os.symlink(r'C:\Users\Jayce\Anaconda3\envs\tf2.3\Lib\site-packages\pth_test.pth', r'C:\Users\Jayce\Anaconda3\envs\tf2.5\Lib\site-packages\pth_test.pth')
    
    
    • 1
    • 2
    • 3
    • 4

    虚拟环境:tf2.5运行编译为pyc.py,没有报错,证明导入成功,方法可行!如果你有更多的虚拟环境,依次生成软连接即可(不要直接copy软连接,这样复制的是源文件)。

    3.3添加 PYTHONPATH环境变量,实现项目直接调用工具函数

    通过如下路径:我的电脑 -> 属性 -> 高级系统配置 -> 环境变量 -> 系统变量 新建一个名为 PYTHONPATH的系统环境变量:
    在这里插入图片描述
    PYTHONPATH直接填入工具函数的父路径即可:
    在这里插入图片描述
    点击确定保存完毕后,任意打开1CMD,输入下述代码:

    echo %PYTHONPATH%
    
    • 1

    查看PYTHONPATH变量是否添加成功:
    在这里插入图片描述
    运行编译为pyc.py,没有报错,证明导入成功,方法可行!

    注意

    1. CMD一定要新开,不然读取不了你新增的变量;
    2. 如果是Pycharm,需要彻底关闭所有PyCharm窗口后,再次执行代码,才可正常获取环境变量。不然会出现在CMD中可以获取环境变量,PyCharm未正常读取的问题。

    3.4解决方法

    4.总结🤔

    1. 3.1中的方法需要在每个项目的入口文件中增加两行代码,无法做到全自动,每次我们都要添加,稍微有点麻烦。
    2. 3.2中的方法需要在每个虚拟环境中的site-packages生成软连接,也有点麻烦。
    3. 3.3中的方法只需要添加一个环境变量,简单高效,强烈推荐!!


    渣男!都看到这里了,还不赶紧点赞评论收藏走一波?

  • 相关阅读:
    react实现转盘抽奖功能
    07-树(Tree)结构分析
    智能算力AI破局 英特尔携手百度飞桨,共话AI技术创新引领新征程
    制造业数字化转型峰会,云盒子带来先进制造业数据安全解决方案
    Vue太难啦!从入门到放弃day06——Vue前端路由
    常用傅里叶变换表
    一.node的http模块;二.同步和异步;三.异步操作的实现:ajax;四.jQuery中对ajax封装;五.Node的Web框架
    基于晶体结构算法优化概率神经网络PNN的分类预测 - 附代码
    【无标题】
    Linux驱动开发笔记(六):用户层与内核层进行数据传递的原理和Demo
  • 原文地址:https://blog.csdn.net/qq_15969343/article/details/126622679