V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
Vcide
V2EX  ›  Python

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

  •  
  •   Vcide · 192 天前 · 1056 次点击
    这是一个创建于 192 天前的主题,其中的信息可能已经有所发展或是发生改变。

    大家好,最近在处理 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 是一个非常复杂的项目, 有着很多导入和很多层级, 有没有办法不用一个个全部改成相对导入, 或者有什么自动化的工具可以完成这个动作呢? 抑或是还有更好的处理方法?

    13 条回复    2023-11-03 09:09:37 +08:00
    itskingname
        1
    itskingname  
       192 天前
    把 b 文件夹的绝对路径,加到环境变量 PYTHONPATH 里面。
    cunjuefafafa
        2
    cunjuefafafa  
       192 天前
    import sys
    sys.path.append('b 的绝对路径')

    之后 a 下面的文件夹要避免与 b 的文件夹重名
    Vcide
        3
    Vcide  
    OP
       192 天前
    @cunjuefafafa 谢谢回复您的回复, 确实可以!
    song135711
        4
    song135711  
       192 天前
    export PYTHONPATH='.'
    Vcide
        5
    Vcide  
    OP
       192 天前
    @song135711 请问这样做的话会不会导致命名空间会乱掉, 因为最后要做容器化在生产环境跑.
    julyclyde
        6
    julyclyde  
       192 天前
    @Vcide 我觉得如果你不把 b 改成相对导入的话,即使本次没遇到命名空间冲突的问题,将来也会遇到,这是无穷尽的维护代价

    python 语言没有把新特性作为强制而是向后兼容,导致了无法把新的好处强制交给用户
    Vcide
        7
    Vcide  
    OP
       192 天前
    @julyclyde 谢谢您的建议,我会尝试进行改进的. 主要是 B 项目本身太复杂了,上手难度比较大.
    julyclyde
        8
    julyclyde  
       191 天前
    @Vcide 看能不能让 B 作者同事改,嘿嘿……
    NoOneNoBody
        9
    NoOneNoBody  
       191 天前
    楼上添加路径的方式可以利用 __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
        10
    Maerd  
       190 天前
    盲猜同事的是 pycharm ,你的是 vscode
    第一种方案,添加 PYTHONPATH
    第二种方案,使用 pycharm
    Vcide
        11
    Vcide  
    OP
       190 天前
    @Maerd 哈哈哈,不是的. 他用的是 VSCode.我现在用 PyCharm 把他代码重构了
    Vcide
        12
    Vcide  
    OP
       190 天前
    @NoOneNoBody 谢谢,最后也是这样做了, 全部改成了相对依赖. 不过 B 项目有一些对于二进制文件的调用, 现在先用__file__处理了一下,可能需要再写一个配置类来方便调用, 但其实还是有点麻烦.
    song135711
        13
    song135711  
       176 天前
    @Vcide 设置下 Docker 中 WORKDIR
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   2799 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 48ms · UTC 06:13 · PVG 14:13 · LAX 23:13 · JFK 02:13
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.