个人使用vscode碰到的一些python包的引用问题以及尝试解决的一些办法,可能只适用我自己的情况,项目目录大概如下:lib是根目录下的一个文件夹,里面每个文件夹都是一个python 包,都有__init__.py,但是在引用包的时候出现一些找不到包的问题
.
├── other_dir
├── lib
├── ...
lib
├── packageA
├── packageB
├── test.py
packageA
├── __init__.py
├── test.py
└── demo.py
首先,在lib目录下的test.py 使用 import packageA.test 等引入包都是可以的,在两个test.py 中添加如下语句
print('__file__={0:<35} | __name__={1:<20} | __package__={2:<20}'.format(__file__,__name__,str(__package__)))
会得到如下输出语句
__file__=test.py | __name__=__main__ | __package__=None
__file__=/project_root/lib/packageA/test.py | __name__=packageA.test | __package__=packageA
可以看到,lib下的test.py被当作程序的入口,而包目录下的test被当作包的模块,这些是没有问题的
主要问题出在,如果在packageA的test.py 中import了packageB或者同目录下的demo ,如果方式不对可能会报找不到包的错误
假设现在packageA的test.py有如下语句
import demo
import packageB.demo
1.现在去执行lib下的test.py 会报demo找不到的错,原因是在这种情况下,python 会将import后面的当作包名来处理,而整个project中不存在名为demo的package,而只有路径为“demo.py"的同目录下的模块。
2、当你切到packageA目录下执行test.py ,此时demo的应用不会报错,而packageB.demo 的引用会报错,因为此时python 是以packageA目录去找的,因为同目录下存在相对路径为”demo.py"的包,所以import demo 没有报错,而packageA里面没有 packageB 这个包,因为packageB在packageA的外面,所以找不到
两个导入一个是按模块,一个是按路径
解决方法:
一、如果只是在lib目录,也就是包外面的目录下能够运行,可以简单的把所有的形如 import demo 这样的同目录下的模块前面加上 . ,即
import .demo
import packageB.demo
这样. 实际上就会被解析成packageA,也就是包名,就不是按路径而是按照包名来进行查找包了,但是这种方法适用于你在包的外面去调用所有的包,如果你想切换到包里面还是会报错,这次的错误是 相对包名的错误,就是加的这个 . 导致的
二、如果你既想在包外面运行,在某个包内又能够单独运行,可以在 packageA的test.py 中参考如下写法
import sys
sys.path.append('..')
import packageA.demo
import packageB.demo
sys.path.append('..') 实际上把 lib这个目录添加到了当前查找包的路径中,这个路径取决于你的实际结构,你可以用绝对路径或相对路径,但是相对路径要注意哪个是根目录,sys.path.append('lib')会报错,应为lib 不是packageA里面的文件,".."实际上就是test.py 所在目录(packageA)的上级目录(lib)
使用这种写法,在lib,内外都是可以运行的,添加路径实际上就是告诉python 去哪个路径下面找模块
PS:如果想让某个文件以某个包模块方式运行而不是作为主程序的入口,可以试一下在lib 目录下运行
python -m packageA.test