【问题标题】:__file__ does not exist in Jupyter Notebook__file__ 在 Jupyter Notebook 中不存在
【发布时间】:2016-12-31 17:17:01
【问题描述】:

我在使用 Python 3.4.2 的 Jupyter Notebook 服务器 (v4.2.2) 和 我想使用全局名称__file__,因为笔记本会从其他用户那里克隆,并且我必须在一个部分中运行:

def __init__(self, trainingSamplesFolder='samples', maskFolder='masks'):
    self.trainingSamplesFolder = self.__getAbsPath(trainingSamplesFolder)
    self.maskFolder = self.__getAbsPath(maskFolder)

def __getAbsPath(self, path):
    if os.path.isabs(path):
        return path
    else:
        return os.path.join(os.path.dirname(__file__), path)

__getAbsPath(self, path) 检查path 参数是相对路径还是绝对路径,并返回path 的绝对版本。所以我以后可以安全地使用返回的path

但我得到了错误

NameError: 名称 '__file__' 未定义

我在网上搜索了这个错误,找到了我最好使用sys.argv[0]的“解决方案”,但是print(sys.argv[0])返回

/usr/local/lib/python3.4/dist-packages/ipykernel/__main__.py

但正确的笔记本位置应该是/home/ubuntu/notebooks/

感谢来自 Martijn Pieters (cmets) 的参考 How do I get the current IPython Notebook name 最后一个答案(不接受)非常适合我的需求:

print(os.getcwd())

/home/ubuntu/笔记本

【问题讨论】:

标签: python-3.x path jupyter


【解决方案1】:

如果您想获取脚本运行所在目录的路径,我强烈建议您使用,

os.path.abspath('')

优势

  • 它适用于 Jupyter Notebook
  • 它在 REPL 中工作
  • 它不需要 Python 3.4 的 pathlib

请注意,__file__ 具有优势的一种情况是,当您从目录 A 调用 python 但在目录 B 中运行脚本时。在这种情况下,上述情况以及大多数其他方法将返回 A,而不是 B。但是对于 Jupyter notbook,你总是得到.ipyn 文件的文件夹,而不是你启动jupyter notebook 的目录。

【讨论】:

  • 这对我不起作用。当我用造纸机运行笔记本时,它给了我“工作目录”。
  • 这令人惊讶。在我的测试中,所有 3 个场景都有效。这可能是因为造纸厂(我不熟悉它)?
  • @Shital,untidyhair 是正确的。就像下面 mab 的其他建议一样,这不起作用。它只是给你 cwd。
【解决方案2】:

__file__ 可能对您不可用,但实际上您可以通过不同的方式获取笔记本所在的当前文件夹。

全局变量中有痕迹,如果你调用globals(),你会看到有一个带有键_dh的元素,这可能会对你有所帮助。在这里,我如何设法加载与我的笔记本位于同一文件夹中的 data.csv 文件:

import os

current_folder = globals()['_dh'][0]

# Calculating path to the input data
data_location = os.path.join(current_folder,'data.csv')

【讨论】:

  • 哇,恭喜@shytikov,您的方法确实有效,应该是首选答案。您已经找到了一种避免丑陋的 JS 黑客攻击的方法。非常感谢。现在,如果我们能找到获取笔记本名称的方法...
  • 看起来这在 Notebook 中有效,但在常规 Python 解释器中(至少在作为模块导入时)。我在使用 Jupyter 内核和常规 Python 解释器之间切换,所以我需要在两者上都可以使用的东西。我想我将求助于环境变量。
  • 这在 JupyterLab 和 Pycharm 中都适用于我,而其他建议则没有。
  • 为什么不用os.getcwd() 代替globals()['_dh'][0]
  • 当我使用 papermill 从不同的目录执行笔记本时,这对我不起作用。 os.getcwd()globals()["_dh"] 都显示了我运行 papermill 命令的目录,而不是笔记本模板的目录或执行的笔记本将登陆的目录
【解决方案3】:

在现代 Python (v3.4+) 中,我们可以使用 pathlib 来获取笔记本的目录:

from pathlib import Path

cwd = Path().resolve()
# cwd == PosixPath('/path/to/this/jupyter/ipynb/file's/directory/')

# or this way, thanks @NunoAndré:
cwd = Path.cwd()
# cwd == PosixPath('/path/to/this/jupyter/ipynb/file's/directory/')



更新

@ShitalShah 我无法重现您报告的错误。无论应用程序启动的当前工作目录是什么,Jupyter notebook 似乎都可以正常工作。

示例:文件 ~/dir1/dir2/untitled.ipynb 和 Jupyter 笔记本在 ~/dir1 中启动:

Jupyter notebook 开始于~/dir1/dir2:

【讨论】:

  • @ShitalShah 请查看更新后的答案。也许您可以澄清一下,您遇到的问题是什么。
  • Path 有一个专门的类方法:Path.cwd()
  • @mac,这不起作用。如果您在笔记本中更改 cwd,然后重新执行该单元格,它将为您提供新的 cwd,而不是 notbook 的位置。这是 Jupyter Notebook 中非常缺少的功能。我不得不求助于涉及 Javascript 的黑客攻击。什么皮塔饼。
  • @germ 你说我更新的帖子中的场景是不可能的吗? “如果您在笔记本中更改 cwd”是什么意思? :)
  • @mab:试试import os;os.chdir('path/to/new/dir')。如果你现在同时尝试Path.cwd()Path().resolve(),它们都指向path/to/new/dir,而不是你笔记本的位置!
【解决方案4】:

无法获取笔记本的路径。您可能会找到一种仅在一种环境中有效的方法(例如os.getcwd()),但如果笔记本以不同的方式加载,则不一定有效。

相反,尝试编写笔记本,使其不需要知道自己的路径。如果执行诸如获取密码之类的操作,请确保快速失败/如果这不起作用,则打印错误,而不是默默地尝试继续。

另请参阅:https://github.com/ipython/ipython/issues/10123

【讨论】:

  • 你说得对,使用 os.getcwd() 无法获取笔记本的路径。这只是得到 cwd。如果您在笔记本中更改了它,然后返回该单元格,您将不会获得笔记本目录。这是一个大问题。不,我不同意你应该编写你的脚本,这样它就不需要知道它在哪里。这样做有很好的理由,例如复制到另一个位置。
猜你喜欢
  • 2021-09-25
  • 1970-01-01
  • 1970-01-01
  • 2020-02-15
  • 1970-01-01
  • 2021-02-23
  • 2019-11-24
  • 2020-04-23
  • 2017-06-12
相关资源
最近更新 更多