【问题标题】:Import local package from local script从本地脚本导入本地包
【发布时间】:2021-05-30 17:13:03
【问题描述】:

我有这个项目结构:

.
├── README.md
├── my_project
│   ├── __init__.py
│   ├── config.py
│   ├── integrations
│   │   ├── __init__.py
│   │   └── google_places.py
├── requirements.txt
└── scripts
    └── my_script.py

my_script.py 我有:

from my_project.integrations.google_places import GooglePlaces

但是在运行python scripts/my_script.py 时出现以下错误:

ModuleNotFoundError: No module named 'my_project'

在本地我可以 pip install -e . 我的包(通过添加 setup.py 到组合中),但是由于我需要从 GitHub Actions 运行它,所以我觉得追求相同的途径没有意义。

我一直在阅读有关操纵 sys.path 的文章,但它似乎有点骇人听闻。

由于这是一个相当常见的设置(我猜),修复上述错误的推荐方法是什么?如果有意义,我可以更改项目结构。

【问题讨论】:

    标签: python


    【解决方案1】:

    这也让我感到惊讶,但是在阅读了这个相当全面的答案https://stackoverflow.com/a/54613085/6180150,并进入了关于python 中module search path 的链接python 文档之后,我认为你必须调整PYTHONPATH。问题是这两个python文件位于两个单独的包中,即scriptsmy_project,所以my_script.py找不到google_places.py,因为PYTHONPATH只包含当前包而不是父文件夹和 python 只会搜索以下目录(请参阅上述搜索路径文档):

    • 包含输入脚本的目录(或未指定文件时的当前目录)。
    • PYTHONPATH(目录名称列表,与 shell 变量 PATH 语法相同)。
    • 依赖于安装的默认值。

    也在此评论中:Python: 'ModuleNotFoundError' when trying to import module from imported package 上述答案的回复者很好地解释了调整PYTHONPATH 并不是一个真正的解决方案(尽管我也会这么觉得),但是根据 python 记录的解决方案也是如此。

    如果可能的话,如果我处于你的位置,我想我会将my_script.py 移动到my_project 包中,如下所示。

    .
    ├── README.md
    ├── my_project
    │   ├── __init__.py
    │   ├── config.py
    │   ├── integrations
    │   │   ├── __init__.py
    │   │   └── google_places.py
    │   └── my_script.py
    └── requirements.txt
    

    然后你可以调整你的导入:

    from integrations.google_places import GooglePlaces
    

    编辑:

    如果你喜欢使用下面的文件树结构(甚至原来的应该可以)。

    .
    ├── README.md
    ├── my_project
    │   ├── __init__.py
    │   ├── config.py
    │   ├── integrations
    │   │   ├── __init__.py
    │   │   └── google_places.py
    │   └── scripts
    │       └── my_script.py
    └── requirements.txt
    

    你可以像这样修改你的 sys.path,然后使用原来的 import 语句:

    import sys
    import os
    
    sys.path.insert(0, os.getcwd())
    from my_project.integrations.google_places import GooglePlaces
    

    【讨论】:

    • 感谢您的回复。我提到scripts 不是一个包,因为它不包含任何__init__.py 文件。但是,我已将scripts 移动到my_project 下,将其作为一个包,根据您的建议更新了导入并使用python my_project/scripts/my_script.py 运行脚本,但它失败了:ModuleNotFoundError: No module named 'integrations'
    • 是的,这是有道理的,因为python会再次根据其搜索模型进行搜索:“包含输入脚本的目录(或未指定文件时的当前目录)”。这意味着它在my_project/scripts/PYTHONPATH 内部查找。如果您需要将其保留在scripts 下,则应更新sys.path
    • @linkyndy 我刚刚添加了另一个示例代码,它适应了sys.path,因此您可以成功导入模块。它还应该允许使用原始文件树结构。让我知道它是否有效:)
    • 我最终将所有脚本移至顶层,scripts 下不再嵌套。感谢您提供帮助!
    • 我也会这样做。感觉不那么老套了:D
    猜你喜欢
    • 1970-01-01
    • 2021-09-16
    • 1970-01-01
    • 2015-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多