5

Python 包导入的困惑

 3 years ago
source link: https://www.v2ex.com/t/813185
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

V2EX  ›  Python

Python 包导入的困惑

  zxCoder · 2 天前 · 2381 次点击

下载了一个 python 项目,目录是这样子的

- XXXProject
  - A
    - __init__.py
    - xxx.py
    - yyy.py
    - ...
  - scripts
    - zzz.sh

xxx.py 的内容是

from A.yyy import YY
if __name__ == "__main__":
    # .....

yyy.py 的内容是

class YYY():
    # .....

zzz.sh 的内容是

python A/xxx.py

然后我就按照 README 所说,在项目根目录下执行 sh scripts/zzz.sh,结果报错了,错误是

ModuleNotFoundError: No module named 'A'

这是为什么呢?

第 1 条附言  ·  1 天前

按大家的说法....这就是这个项目的README本身写错了?

31 条回复    2021-11-05 22:32:26 +08:00

mangoDB

mangoDB   2 天前

from yyy import YY

Trim21

Trim21   2 天前 via Android

把 XXXProject 文件夹加到 python path 环境变量里

Latin

Latin   2 天前

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import os.path as osp
import sys


def add_path(path):
if path not in sys.path:
sys.path.insert(0, path)


this_dir = osp.dirname(__file__)

lib_path = osp.join(this_dir, '..', 'lib')
add_path(lib_path)

ch2

ch2   2 天前

需要加 path

misaka19000

misaka19000   2 天前

要把 XXXProject 这个目录加到 PythonPATH 里面去

export PYTON_PATH=$PYTHON_PATH:/xxx/xxx/XXXProject

sudoy

sudoy   2 天前

@mangoDB `from yyy import YY` +1 不需要`A.yyy`, 因为 xxx.pyyyy.py 在同一个文件夹下面

misaka19000

misaka19000   2 天前

@Vegetable 谁给你自动添加? Python 怎么知道哪个目录是根目录

Vegetable

Vegetable   2 天前

@misaka19000 python 的 sys.path 第一位永远是""

misaka19000

misaka19000   2 天前

@Vegetable 有的时候是不会在项目的根路径执行程序的

2i2Re2PLMaDnghL

2i2Re2PLMaDnghL   2 天前

我觉得更可能你没有安装这个项目,因为 git clone 下来的不会自动安装
如果根目录下有 setup[.]py 的话,应先运行 pip install -e . (你可能会希望做一个 venv ,以免把 A 安装到系统里去)

jaredyam

jaredyam   2 天前

我的观点,未验证:
1. zzz.sh 的执行路径(在根目录)和执行方式( python A/xxx.py )没有问题
2. 问题是此时 A/xxx.py 被看作为为一个脚本文件直接执行,却使用了 from A.yyy import YY 从它外部的一个包(其实是包括自己的包,但包不包括自己不重要)导入模块 yyy ,按理来说直接 from yyy import YY 就好了,不需要考虑 A ,直接把 yyy 作为同级模块导入即可
3. 但是按照 2 的解决思路,A 的结构就显得很怪异,A 被强行看作一个包(有__init__.py ),但却又包含脚本。一般实践中,xxx.p 应该被拿出来,放在包外面,比如和 scripts/同级,然后在 zzz.sh 中 python xxx.py ,具体放哪看脚本干的事情,但放包里就是有问题

2i2Re2PLMaDnghL

2i2Re2PLMaDnghL   2 天前

@2i2Re2PLMaDnghL 发现排版不太好看清,
```
pip install -e .
```
最后的 dot 是必要的。

2i2Re2PLMaDnghL

2i2Re2PLMaDnghL   2 天前

@jaredyam 确实挺怪的,不过一般实践应该是为 A.xxx:main 设置一个 entrypoint ,或者 python -m A.xxx

xingheng

xingheng   2 天前

我认为 sys.path 都是扯犊子,我从来不那么干,除非在写加载动态化插件。Python 会把当前工作目录加入到 sys.path 里,这一点儿就够了。

直接改写 zzz.sh:
python ../A/xxx.py

orzglory

orzglory   2 天前

@Latin sys.path.insert() 这种很脏的做法, 就不要再传播了.


Python 是通过 __init__.py 文件来区分 普通文件夹和 package 目录的.


你 XXXProject/ 目录下, 并没有__init__.py 文件, 你的脚本, 并不会认为这是 Python 项目.


很久不写 py 了. 建议你添加个 __init__.py 文件在 XXXProject/ 目录, 再试一下.


Python 的项目路径环境, 没什么复杂的.

orzglory

orzglory   2 天前

@misaka19000 Python 社区, 都凋零成这样了吗?

一个小脚本, 都开始教他添加环境变量了?

阿西吧.

orzglory

orzglory   2 天前

@xingheng 你的回复, 还算正常. ls 的都是什么鬼.

你的回复, 配合我上面的建议的修改. 应该就正常了.

zxCoder

zxCoder   2 天前

@orzglory 我用一楼的方法改好了。。。。但是谁能告诉我这是什么原因,python 版本问题吗?

这个项目我看也没有人提出相关的 issue ,肯定是能跑的

Latin

Latin   2 天前

基本上开源出来的算法模块现在都是这个套路吼

misaka19000

misaka19000   2 天前   ❤️ 1

@orzglory 我就教了怎么了,你哪来的优越感?下次怼人之前麻烦先把你写的代码亮出来看看都是些什么东西

oOoOoOoOoOo

oOoOoOoOoOo   2 天前 via Android

working_dir 决定一切

ila

ila   2 天前 via Android

你去看 flask 等项目的目录结构,
被 import 的路径里包含了__init__.py 文件。
而且官方文档也是建议这样做。

ila

ila   2 天前 via Android

不要第一步就改环境变量,该设置的都在安装(软件和包)时设置好了

XIVN1987

XIVN1987   2 天前

PEP 328: all import statements be absolute by default (searching sys.path only) with special syntax (leading dots) for accessing package-relative imports.
“from A.yyy import YY” 显然是个绝对导入,所以 python 肯定是在 sys.path 中的路径中查找 A 。。那程序要想执行只有两种方法:
1 、把 XXXProject 的路径加入 sys.path
2 、把 A 安装到现有的 sys.path 中去,比如 “lib/site-packages” 目录下

XIVN1987

XIVN1987   2 天前

```
>>> import sys
>>> for x in sys.path: print(repr(x).replace(r'\\', '/'))
''
'C:/Python36/python36.zip'
'C:/Python36/DLLs'
'C:/Python36/lib'
'C:/Python36'
'C:/Python36/lib/site-packages'
```

当前目录确实在 sys.path 中,但当前目录指的是被 python.exe 直接执行的那个 xxx.py 所在的目录,所以 XXXProject/A 的路径在 sys.path 中,但 XXXProject 不在 sys.path 中。
所以题主的“from A.yyy import YY”执行出错,而一楼的“from yyy import YY”执行正常。

Trim21

Trim21   2 天前 via Android

@Latin 你没注意到这几行实际上被注释掉了吗…

Recommend

  • 61
    • www.jisilu.cn 6 years ago
    • Cache

    作为大龄剩男的困惑

    作为大龄剩男的困惑 - 本人89年的大龄剩男一个,十年前来看是不错的小伙子,但是十年中由于傻逼眼光独到,只投资股市债市,错过了多少次投资买房的暴富机会,让自己财富自由之路缓慢艰辛对于爱情更是悲哀,太早遇到一个美女,甘愿给人家当了十六年备胎,美女每一次...

  • 70
    • 新浪科技 tech.sina.com.cn 6 years ago
    • Cache

    惊喜还是困惑? 专家热议人工智能发展痛点

    人民网北京5月12日电(赵竹青)“人类已经进入人工智能时代,这既让我们惊奇、惊喜,也时常让我们陷入困惑。”吴曼青院士的一句话总结了我们当前对于人工智能的态度。10日-11日,由中国工程院信息与电子工程学部主办,中国电子科技集团有限公司等单位

  • 58

    程序员 - @AaronWang13 - 16 年普通一本高校毕业,大学当时是学的 c/c++,进了上一家公司开始做.net.在上家公司做的就是搬运的工作,框架都是公司封装好的,而且任务量大 出差也多没有私人时间,工作上的都是复制粘贴,在

  • 105

    作为一个老技术人,今天不聊技术,就聊点技术人员职业发展的事情:对技术管理岗位的认知,比如技术总监。 先贴一张技术人员职业发展路线图,按照管理路线和技术路线区分。在国外管理路线和技术路线的职位会按照 IT Manager 和 Tec...

  • 62
    • www.10tiao.com 6 years ago
    • Cache

    令人困惑的TensorFlow!

    选自jacobbuckman.com 作者:Jacob Buckman

  • 9

    我们见到的Go包的导入路径常常以github.com、bitbucket.org等代码托管站点的域名为前缀,这样的包导入路径有一个问题,那就是 当G...

  • 11
    • www.v2ex.com 3 years ago
    • Cache

    关于 Python 包导入的问题

    V2EX  ›  Python 关于 Python 包导入的问题   still97 · 2 小时 49 分钟前 · 339 次点击 ...

  • 3
    • tonybai.com 3 years ago
    • Cache

    理解Golang包导入

    理解Golang包导入 Golang使用包(package)这种语法元素来组织源码,所有语法可见性均定义在package这个级别,与Java 、python等语言相比,这算不上什么创新,但与C传统的include相比,则是显得“先进...

  • 8
    • www.mindg.cn 3 years ago
    • Cache

    python中代码运行的困惑

    python中代码运行的困惑 网上看到的代码: def clear_list(l):ll = [1,2,3]clear_list(ll)print(l...

  • 6

    V2EX  ›  Python [困惑] 写好的 Python 应用如何分发?  

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK