求帮助, 无法使用同事的项目, Python 移动项目后导入失效

2023-10-18 10:11:34 +08:00
 Vcide

大家好,最近在处理 Python 相关的项目的时候遇到了问题,希望可以请教一下大家. 我希望将同事写好的项目放入我的项目 a 中使用, 假设他的项目称之为 b,于是我直接将其放入我项目的根目录下, 简化后的项目结构如下:

.
├── __init__.py
├── b
│   ├── __init__.py
│   ├── config.py
│   └── process.py
└── main.py

其中 main.py

from b.process import process

if __name__ == '__main__':
    process()

config.py:

PDF_FILE = 'apc.pdf'

process.py

from config import PDF_FILE


def process():
    print('Processing PDF file:', PDF_FILE)


if __name__ == '__main__':
    process()

之后我从根目录(b 的父目录, main.py所在的文件夹)运行了

python main.py

出现了 Error

Traceback (most recent call last): File "/Users/xxx/a/main.py", line 1, in <module> from b.process import process File "/Users/xxx/a/b/process.py", line 1, in <module> from config import PDF_FILE ModuleNotFoundError: No module named 'config'

之后我从我项目(项目 a)的父目录中运行

python -m a.main

依然会有一样的错误.

如何解决这种情况呢, 我知道将 b\process.py中的 from config import PDF_FILE 改为 from .config import PDF_FILE 避免上面的错误. 但是实际中的 b 是一个非常复杂的项目, 有着很多导入和很多层级, 有没有办法不用一个个全部改成相对导入, 或者有什么自动化的工具可以完成这个动作呢? 抑或是还有更好的处理方法?

1304 次点击
所在节点    Python
13 条回复
itskingname
2023-10-18 10:21:18 +08:00
把 b 文件夹的绝对路径,加到环境变量 PYTHONPATH 里面。
cunjuefafafa
2023-10-18 10:23:14 +08:00
import sys
sys.path.append('b 的绝对路径')

之后 a 下面的文件夹要避免与 b 的文件夹重名
Vcide
2023-10-18 11:07:22 +08:00
@cunjuefafafa 谢谢回复您的回复, 确实可以!
song135711
2023-10-18 11:30:50 +08:00
export PYTHONPATH='.'
Vcide
2023-10-18 11:59:46 +08:00
@song135711 请问这样做的话会不会导致命名空间会乱掉, 因为最后要做容器化在生产环境跑.
julyclyde
2023-10-18 12:45:59 +08:00
@Vcide 我觉得如果你不把 b 改成相对导入的话,即使本次没遇到命名空间冲突的问题,将来也会遇到,这是无穷尽的维护代价

python 语言没有把新特性作为强制而是向后兼容,导致了无法把新的好处强制交给用户
Vcide
2023-10-18 13:51:10 +08:00
@julyclyde 谢谢您的建议,我会尝试进行改进的. 主要是 B 项目本身太复杂了,上手难度比较大.
julyclyde
2023-10-18 20:07:31 +08:00
@Vcide 看能不能让 B 作者同事改,嘿嘿……
NoOneNoBody
2023-10-19 13:52:15 +08:00
楼上添加路径的方式可以利用 __file__ 计算相对路径,但我觉得这样做,纯脚本没问题,但遇到编译或部署就难说了

第二种方式:
重写 b 内所有文件的 import
b 内的所有项目 import 都需要改为 from b.xxxx import ... 就是使用 b 开头的完整 namespace
即使同级也是,例如上述 from config import PDF_FILE 改为 from b.config import PDF_FILE
注意 b 各层__init__.py 是必须有的,即使它是个零字节空文件
当然与三方包无关,只是与 b 有关的全都要改

这样做是归一化,肯定麻烦,但它的好处不影响其他项目及将来,也不会因为整体项目挪动位置导致要改 sys.path.append

第三种方式
b 单独打包,不要放进 a 内,作为三方包使用,当然部署时也要安装这个包
最简单是写一个.pth 扔进 site-packages
这种方式难以与 a 交互,且基本上 b 视为不再改动(或独立改动),如果将来要和 a 融合还是麻烦
Maerd
2023-10-19 16:20:11 +08:00
盲猜同事的是 pycharm ,你的是 vscode
第一种方案,添加 PYTHONPATH
第二种方案,使用 pycharm
Vcide
2023-10-20 10:13:04 +08:00
@Maerd 哈哈哈,不是的. 他用的是 VSCode.我现在用 PyCharm 把他代码重构了
Vcide
2023-10-20 10:16:43 +08:00
@NoOneNoBody 谢谢,最后也是这样做了, 全部改成了相对依赖. 不过 B 项目有一些对于二进制文件的调用, 现在先用__file__处理了一下,可能需要再写一个配置类来方便调用, 但其实还是有点麻烦.
song135711
2023-11-03 09:09:37 +08:00
@Vcide 设置下 Docker 中 WORKDIR

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/983002

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX