__file__在Jupyter Notebook中不存在


78

我在使用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获得当前的IPython Notebook名称(评论),最后一个答案(不被接受)非常适合我的需求:

print(os.getcwd())

/ home / ubuntu / notebooks


2
__file__适用于模块和Python脚本,不适用于笔记本。您找到的答案不适用于此处。
马丁·彼得斯

Answers:


53

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

os.path.abspath('')

好处

  • 它可以从Jupyter Notebook工作
  • 它来自REPL
  • 它不需要Python 3.4的pathlib

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


2
这对我不起作用。当我用纸厂运行笔记本时,它给了我“工作目录”。
untidyhair '19

真令人惊讶 在我的测试中,所有3种情况均有效。是因为造纸厂(我不熟悉)吗?
Shital Shah

3
@ Shital,untidyhair是正确的。就像下面来自mab的其他建议一样,这不起作用。它只是给您cwd。
胚芽

18

__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')

2
哇,恭喜@shytikov,您的方法确实有效,应该是首选方法。您已经找到了避免难看的JS骇客的方法。非常感谢。现在,如果我们能获得笔记本名称的话……
胚芽

看起来这可以在Notebook中使用,但不能在常规的Python解释器中使用(至少当作为模块导入时)。我在使用Jupyter内核和常规Python解释器之间进行切换,因此我需要在两者上都可以使用的东西。我想我将诉诸于环境变量。
凯尔·巴伦

这在JupyterLab和Pycharm中都对我有效,而其他建议则没有。
aimfeld

16

无法获得笔记本的路径。您可能会找到一种只能在一个环境(例如os.getcwd())中使用的方法,但是如果笔记本计算机以其他方式加载,则不一定能使用。

相反,请尝试编写笔记本,以便它不需要知道自己的路径。如果执行类似获取密码的操作,则请确保快速失败/如果此方法无效则打印错误,而不是默默尝试继续操作。

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


没错,使用os.getcwd()无法获得笔记本的路径。这只是得到CWD。如果您在笔记本中进行了更改,则返回该单元格,将不会获得笔记本目录。这是一个巨大的问题。不,我不同意您应该编写脚本以使脚本不需要知道脚本的位置。这样做的理由非常充分,例如将副本复制到另一个位置。
胚芽

15

在现代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 Notebook开始于~/dir1

Jupyter Notebook从〜/ dir1开始

Jupyter Notebook开始于~/dir1/dir2

Jupyter Notebook在〜/ dir1 / dir2中启动


1
不幸的是,如果您从父文件夹启动Jupyter笔记本命令,这会中断
Shital Shah

@ShitalShah,请参阅更新的答案。也许您可以澄清一下您遇到的问题。
人与生物圈计划

1
请忽略我的评论。您是正确的,这在Jupyter Notebook和REPL中均有效,但是还有另一种方法不需要Python 3.4 pathlib,我也添加了该答案。
Shital Shah

1
Path为此提供了一个类方法:Path.cwd()
NunoAndré19年

2
@mac,这不起作用。如果您在笔记本中更改了cwd,然后重新执行该单元,它将为您提供新的cwd,而不是notbook的位置。这是Jupyter Notebook中非常缺少的功能。我不得不求助于涉及Java语言的黑客。真是皮塔饼。
胚芽
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.