一个小项目,需要用到包内模块间调用,包外有文件又要调用包内模块。
C:\USERS\XXX\DESKTOP\TEST
│ 1.py <===调用lib02.py所有属性
│
└─lib
│ lib01.py
│ lib02.py <===调用lib01.py所有属性,调用sublib.sublib02.py所有属性
│
└─sublib
sublib01.py
sublib02.py <== 调用sublib01.py所有属性
单纯用import导入,一定会遇到要么1.py执行错误,要么包内lib02.py执行错误。
例如如下调用关系:
解决思路,方法1,2是失败思路,方法3能解决问题但效率低,方法4尝试但失败。最有效的是方法5:
方法1、在目录内增加空内容文件:__init__.py ------------>不能解决问题
如在sublib目录下增加__init__.py文件,执行lib02.py会报错:
1 Traceback (most recent call last): 2 File "C:\Users\xxx\Desktop\test\lib\lib02.py", line 1, in <module> 3 from sublib import sublib02 4 File "C:\Users\xxx\Desktop\test\lib\sublib\__init__.py", line 6, in <module> 5 import sublib01 6 ModuleNotFoundError: No module named 'sublib01'
方法2、在__init__.py增加import xxxx ------------>不能解决问题
如在sublib目录下增加__init__.py文件中增加import sublib01、 import sublib02,执行lib02.py会报错:同上
方法3、在每个__init__.py文件中使用代码将当前目录加入Python系统环境变量 ------------>解决问题,更完美方案其实是方法4,方法5
1 import os 2 import sys 3 rootpath = str(os.path.dirname(os.path.abspath(__file__))) 4 sys.path.append(rootpath)
总结:由于一直习惯使用Sublime Text 3写点代码,所以单纯从import入手无法解决,需要借助环境变量解决问题。
另外如果使用PyCharm,该工具会自动在编译执行时增加文件间调用关系,比纯文本写代码方便一点,但还是不能完全解决问题。
感谢给我提供解决方案的同事:XKZ
经过1年多时间,又找到2个方法
方法4、虚拟环境activate文件加项目路径
极客时间 Python核心技术与实战 景霄 Facebook资深工程师 课程第13课提到的如下内容:
这里我稍微提一下 Python 的 Virtual Environment(虚拟运行环境)。Python 可以通过 Virtualenv 工具,非常方便地创建一个全新的 Python 运行环境。
在一个 Virtual Environment 里,你能找到一个文件叫 activate,在这个文件的末尾,填上下面的内容: export PYTHONPATH="/home/ubuntu/workspace/your_projects"
这样,每次你通过 activate 激活这个运行时环境的时候,它就会自动将项目的根目录添加到搜索路径中去。
这个方法经过试验有2个结论,1、在linux环境下也许更好用;2、我使用的python虚拟环境管理更方便的virtualenvwrapper-win以及sublime(不具备自动管理包之间关系能力)情况下,此方法无效。
方法5、site-packages目录下增加 xxx.pth文件
我不甘心要在每个__init__.py都加环境变量修改脚本,查了资料,终于还是发现了另外一个比较一劳永逸的方法,只需要一次操作:
适用范围:使用sublime,pycharm编写在本机环境或【python虚拟环境virtualenvwrapper-win】运行的工程。
原理及方法:python运行时都会先去site-packages目录下寻找.pth文件,如果有就先加载里面的路径到环境变量中。
在python环境(本机本土化或虚拟机环境 <-- 特别好用)如:D:\Python36\Lib\site-packages目录下增加一个 xxx.pth文件,
.pth文件内容是要运行项目的绝对地址,windows操作系统记得使用 \\ 作为分隔符。
注意:如果项目路径中有中文,运行python编译就会报错:
解决办法:1、把项目路径换成英文;
2、修改python环境源码 X:\Python36\lib\site.py的159行,由【f = open(fullname, "r")】修改为【f = open(fullname, "r",encoding='utf-8')】
为什么不是修改163行?因为在163行执行前的159行才是读取文件的操作,这里的打开编码格式直接影响了163行
大概就这样解决了包引用的问题,由于没有经过太多复杂调用,到目前为止都没有出现问题,如果这个方法不好用,请留言。