运行 与 jupyter nbconvert 在不同目录中的 jupyter notebook

Run a jupyter notebook in a different directory with jupyter nbconvert

我的笔记本有一个目录结构:

notebook.py 文件和 notebook.ipynb 文件与 JupyText 链接:我们将 .py 文件保存在源代码管理中(没有输出或元数据),我们将 .ipynb 文件用作常规笔记本. IntelliJ 让我们有机会从两个文件中获取 运行 单元格,但不幸的是,它们具有不同的工作目录。这意味着引用文件变得非常令人头疼,因为相对路径以 ./ 或 ../

开头

为了解决这个问题,我做了一个肮脏的 hack:在根级别(在 main.py 旁边)我定义了一个 project_root.py 具有以下功能:

def get_project_root() -> str:
    return str(Path(__file__).parent)

然后,从笔记本上,我可以这样做:

from project_root import get_project_root
os.chdir(get_project_root())

突然之间,工作目录始终是项目根文件夹,这意味着所有文件路径也是相对于根文件夹的,我的头疼消失了。

输入main.py。 我已经为过程的每个步骤设置了笔记本,一个用于加载数据的笔记本,一个用于预处理的笔记本,一个用于分析的笔记本,一个用于我要训练的每个模型的笔记本,等等。这样做是因为多个较小的文件是比一个大文件更容易协作,而且东西更容易找到。

在我的主文件中,我基本上是这样做的:(删节)

def run(notebook_path: str):
    os.system("jupyter nbconvert --execute {notebook_path}")

run("notebooks/notebook.ipynb")

这样,我可以 运行 以自动化方式完成整个工作流程并测试多个参数或模型或其他任何内容。

但是 jupyter nbconvert 路径的工作目录是 notebooks/ :( 如果 project_root.py 技巧有效,这会很好,但显然,它也找不到我要导入的 python 文件。

ModuleNotFoundError                       Traceback (most recent call last)
<ipython-input-1-b3b128d3ca4d> in <module>
      3 print(os.getcwd()) # prints "~/project-root/notebooks"
      4 
----> 5 from project_root import get_project_root
      6 os.chdir(get_project_root())
      7 import numpy as np

ModuleNotFoundError: No module named 'project_root'

如果我可以修改 jupyter nbconvert 命令的工作目录,或者如果我能以某种方式让 python 导入以另一种(可扩展的)方式工作,我的问题就会得到解决。当然,欢迎任何其他建议。

谢谢亲爱的reader,抽出宝贵时间!

感谢 Sergey K. 的评论,他让我走上了正轨。

我确实将我的项目根目录标记为源文件夹,但这并没有像我希望的那样将该文件夹添加到 PYTHONPATH。我注意到在执行 run ("notebooks/notebook.ipynb") 之前,我的路径是这样的:[a, b, c, d, project_root]。但是一进入notebook,我的路径就是[project_root/notebooks, a, b, c, d],所以它要么使用单独的路径,要么删除当前工作目录并在前面添加一个新目录。

我以编程方式将 project_root 添加到 PYTHONPATH,它也开始出现在我笔记本中的路径中。这解决了我的问题。

总结:在 main.py 中,运行 这一次(我每次 IDE 启动,我知道为什么):

from project_root import get_project_root

if get_project_root() not in os.environ['PYTHONPATH'].split(os.pathsep):
    os.environ['PYTHONPATH'] = os.environ['PYTHONPATH'] + os.pathsep + get_project_root()