使用 src 子文件夹时从配置文件导入

import from config file when using src subfolder

我想在 /src/cool_api.py 中使用我的 get_data()

get_data() 需要从 config/api_config.yaml 导入 API 密钥,这会导致在尝试 b) 时出现 FileNotFoundError。 对于像这样从 src 导入的内容,是否有默认(非 hacky)解决方案?

我有以下文件结构:

|─ config
│  ├─ api_config.yaml
|─ src # marked as Sources Root folder in Pycharm 
│  ├─ cool_api.py
│  └─ ...
├─ tests
│  └─ test_cool_api.py
└─ main.py

我的代码:

# cool_api.py
def get_data():
    import yaml
    import requests

    with open("../config/api_config.yaml") as f:
        config = yaml.load(f, Loader=yaml.SafeLoader)
    return f"cool_api.org?key={config['api_key']}"


if __name__ == "__main__":
    print(get_data())

a) 有效。

# main.py
from cool_api.py import get_data

if __name__ == "__main__":
    print(get_data())

b) 结果为 FileNotFoundError。没有这样的文件或目录:'../config/api_config.yaml'

如何修复我的导入语句?

可选:是否有 Pycharm 用户的快捷方式?

能否在配置文件夹中添加一个空的 __init__.py 文件

这与导入无关,因为您没有导入 YAML 文件,而是将其作为文件打开,并且您使用的是相对于 Python过程。您收到 FileNotFound 错误,因为工作目录是 main.py 所在的目录,从那里向上一个目录,不会有 config/ 目录。

如果您知道配置文件将始终与 cool_api.py 相关,请使用 __file__(这是指向模块绝对路径的内置函数),并从中计算路径那里。

import os

config_dir = os.path.join(os.path.dirname(__file__), '..', 'config')
config_file = os.path.join(config_dir, 'config.yaml')

with open(config_file):
   ...

关于导入,我想说你的文件结构不是最理想的;您现在可以在 main.pyimport cool_api 的唯一原因是 PyCharm 修复了您的 Python 源路径以包含 src/;如果您尝试在控制台中 python main.py,那是行不通的。

我建议将代码结构化为项目根目录中的包:

cool_api/
  __init__.py  # likely mostly empty
  __main__.py  # main entry point
  config.py    # contains `get_data` and others

带有 __main__ 模块的包可以使用(例如)python -m cool_api 或 运行 配置 -> 目标类型:“模块名称”(而不是“脚本路径” ) PyCharm.

中的选项

运行 该选项还有一个额外的好处,即 Python 本身会修复您的模块路径,因此 import cool_api.config 始终有效,并且 from .config import get_data 在包内有效,等等。