Python相对路径导入:从另一个项目目录导入包

2024-04-18 14:06:00 发布

您现在位置:Python中文网/ 问答频道 /正文

我知道在这个话题上有很多问题,但没有一个对我有多大帮助

我有一个python项目目录,即git_project(git存储库)。我想要的是创建一个名为notebooks的单独目录,在那里我将保存所有笔记本,以便使用git_项目进行分析。我不想把笔记本放在git_项目的根目录中。我将git_projectnotebooks目录都保存在一个通用目录中,我的所有项目都保存在这个目录中。我的结构如下:

my_projects
│ 
├── notebooks
│   └── notebook.ipynb
└── git_project
    └── config
        └── cfg.json
    └── source
        └── config.py

{}的内容:

import json
def get_cfg():
     with open('config/cfg.json', 'r') as f:
         cfg = json.load(f)
     return cfg

{}的内容:

import sys
import os

module_path = os.path.abspath(os.path.join('..'))
if module_path not in sys.path:
    sys.path.append(module_path)

from git_project.source.config import get_cfg
get_cfg()

现在,当我在notebook.ipynb中运行代码时,出现以下错误:

---------------------------------------------------------------------------
FileNotFoundError                         Traceback (most recent call last)
<ipython-input-7-6796ee7f0100> in <module>
----> 1 get_cfg()

~/Documents/my_projects/git_project/source/config.py in get_cfg()
      1 def get_cfg():
----> 2     with open('config/cfg.json', 'r') as f:
      3         cfg = json.load(f)
      4     return cfg

FileNotFoundError: [Errno 2] No such file or directory: 'config/cfg.json'

但是,如果我将notebook.ipynb文件移动到git_项目的根目录下。那么我就不明白这个错误了。这只是一个例子。我在git_项目的其他模块中有很多类似的问题,git_项目包含已经在生产环境中运行的代码。所以改变git_项目中的任何东西在这里都是不可行的。 但正如我所说的,我不想将笔记本移动到git_项目中,而是希望将它们保存在一个并行目录中,以便进行分析。如果需要,我可以提供更多信息

我使用的是Python3.6+,它甚至不再需要放入init.py文件来创建目录包

我应该怎么做才能让它工作?任何帮助都将不胜感激


Tags: path项目importgit目录projectconfigjson
3条回答

作为评论中讨论的后续内容

尽管具有相对路径的方法可以工作,但通常最好对项目根使用更具可伸缩性的方法环境变量

在这种情况下,您的笔记本真正独立于项目,可以使用任意数量的笔记本。 下面是一个关于如何在Jupiter中使用ENV变量的好例子。 我更喜欢使用dotenv方法。 在笔记本文件夹中创建.env。将变量添加到项目路径中:

MY_PROJECT_ROOT=/usr/any/path/you/want

然后在你的笔记本上

import os
from dotenv import load_dotenv
load_dotenv()  # this line loads .env file

然后你的代码

module_path = os.path.abspath(os.getenv('MY_PROJECT_ROOT'))
if module_path not in sys.path:
    sys.path.append(module_path)

一个简单的解决方案是更改工作目录

最初,工作目录是笔记本目录:

from sys import path
import os
print("Current Working Directory " , os.getcwd())

输出:

Current Working Directory  /home/user/git_project/notebooks

然后将其更改为项目的根目录:

os.chdir(os.path.dirname(path[0]))
print("New Working Directory " , os.getcwd())

输出:

New Working Directory  /home/user/git_project

之后,项目根目录上具有相对路径的所有导入都应该可以工作

问题是,当您调用open('config/cfg.json', 'r')时,它打开的路径是相对于启动python代码的目录的。在本例中,它是您的my_projects/notebook目录。您可以通过在get_cfg()内的config.py中添加以下打印来看到这一点:

print(os.getcwd())  # this prints out the current working directory
print(__file__)     # this prints out the path of this script

正如Ahmet所建议的,修改到../git_project/config/cfg.json的路径是可行的,但是python实现将绑定到笔记本文件夹位置。如果您决定重新构造笔记本文件夹,它将再次中断。 一种可能的方法是解析脚本路径:__file__

import json
import os
def get_cfg():
    script_dirname = os.path.dirname(__file__)
    config_path = os.path.join(script_dirname, '..', 'config', 'cfg.json')
    with open(config_path, 'r') as f:
        cfg = json.load(f)
    return cfg

类似建议:(Reading file using relative path in python project)。这也是{a2}中建议的方法:

Files which are to be used by your installed library (e.g. data files to support a particular computation method) should usually be placed inside of the Python module directory itself. ... That way, code which loads those files can easily specify a relative path from the consuming module’s __file__ variable.

如果不想触摸git_project中的当前文件,可以在python笔记本中运行更改目录命令,以指向正确的位置:

In [1]: %cd ../git_project

每次重新启动笔记本内核时,需要调用这一行。您还可以验证笔记本中的当前工作目录:

In [2]: %ls

相关问题 更多 >