python - 如何从 Python 的父目录中的包中导入模块?
问题描述
我很难理解 Python 在哪里搜索包和模块。考虑以下目录结构:
.
├── pkg
│ ├── __init__.py
│ └── module.py
└── scripts
├── __init__.py
└── join.py
所有__init__.py
文件都是空的,pkg/module.py
是:
############################################################
# File Name : module.py
############################################################
def method(*args):
return ', '.join(*args)
并且scripts/join.py
是:
############################################################
# File Name : join.py
############################################################
import os
import sys
from pkg import module
def join(*args):
print(module.method(args))
if __name__ == "__main__":
join(*sys.argv[1:])
sys.exit(os.EX_OK)
现在,如果我从根目录运行交互式 python 会话。我可以毫无问题地导入scripts.join
并运行该方法:join
>>> from scripts.join import join
>>> join('a', 'B', 'c', 'D')
a, B, c, D
但是,如果我想join
直接从命令行运行,我会收到导入错误:
$ python3 scripts/join.py
Traceback (most recent call last):
File "scripts/join.py", line 11, in <module>
from pkg import module
ModuleNotFoundError: No module named 'pkg'
令人惊讶的是,如果我移动join.py
到根目录,它可以作为脚本调用:
$ cp scripts/join.py .
$ python3 join.py a b C d E
a, b, C, d, E
所以我想知道在交互式会话中导入和在脚本中导入有什么区别。另外,我如何能够保留目录join.py
内部scripts/
(同时能够从命令行调用它而无需交互式 Python 会话)?
更新:我意识到如果我调整sys.path
问题就会scripts/join.py
消失:
############################################################
# File Name : join.py
############################################################
import os
import sys
sys.path.append('')
from pkg import module
def join(*args):
print(module.method(args))
if __name__ == "__main__":
join(*sys.argv[1:])
sys.exit(os.EX_OK)
现在我可以运行:
$ python3 scripts/join.py a b c d
a, b, c, d
答案中也提出了类似的解决方案。
我想知道这样的调整是安全的还是有更 Pythonic 的解决方案?例如,很明显,如果脚本是从任何其他目录调用的,它将无法工作。有没有更明确的方式要求 Pythonpkg
从父目录导入?(一种可能性是将相对于__file__
脚本中路径的路径附加到sys.path
)
我尝试__init__.py
在根目录中添加一个并导入
from ..pkg import module
但在那种情况下,我总是得到
ValueError: attempted relative import beyond top-level package
解决方案
因为python会尝试从当前文件夹导入文件夹(或py文件)(如果找不到,它会尝试导入你已经安装的模块)。这就是为什么如果你放到join.py
根文件夹,它可以正常运行。
.
├── pkg
│ ├── __init__.py
│ └── module.py
└── scripts
├── __init__.py
└── join.py
如果你想from pkg import module
使用join.py
:
在你的join.py
:
import sys
sys.path.append("..") # python will try to find the module in his parent folder
from pkg import module
在python 文档中:
sys.path:指定模块搜索路径的字符串列表。从环境变量 PYTHONPATH 初始化,加上依赖于安装的默认值。
一开始只有两个路径可以导入sys.argv[0]
和__file__
.(包括系统PATH中的python文件夹)。使用sys.path.append("..")
后可以导入三个路径。
我认为只有你有许多具有相同名称的文件会导致一些问题。
推荐阅读
- git - 如何列出今年 git 提交的时间戳和提交消息?
- python - 如何通过 sys.argv 执行函数
- java - 刷新 RecyclerView 时丢失数据
- javascript - 无法获取屏幕中存在的对象的位置 - Appium (Android)
- python-3.x - 用于 DynamoDB 查询的 Python 代码适用于 v3.6,但不适用于 python 2.7
- javascript - 在html正文中找到一个单词后,将其替换为另一个
- angular - 为什么 viewContainerRef 没有填充多个组件实例?
- sql - PL-SQL 中的触发器
- meteor - 为什么我的 mongodb 查询的更新不总是反映?
- javascript - 执行while循环,直到用户输入有效输入