在ubuntu服务器上开了jupyter,远程访问的时候,在UI界面上删除某个文件,前端提示Delete Failed Invalid response: 500 Internal Server Error。
服务器后端报错信息如下:

[W 11:14:20.929 LabApp] delete /data/jiangtan/untitled.txt
[E 11:14:20.931 LabApp] Uncaught exception DELETE
    Traceback (most recent call last):
      File "/home/jiangtanzju/software/anaconda3/lib/python3.7/site-packages/tornado/web.py", line 1592, in _execute
        result = yield result
      File "/home/jiangtanzju/software/anaconda3/lib/python3.7/site-packages/tornado/gen.py", line 1133, in run
        value = future.result()
      File "/home/jiangtanzju/software/anaconda3/lib/python3.7/site-packages/tornado/gen.py", line 326, in wrapper
        yielded = next(result)
      File "/home/jiangtanzju/software/anaconda3/lib/python3.7/site-packages/notebook/services/contents/handlers.py", line 235, in delete
        yield gen.maybe_future(cm.delete(path))
      File "/home/jiangtanzju/software/anaconda3/lib/python3.7/site-packages/notebook/services/contents/manager.py", line 279, in delete
        self.delete_file(path)
      File "/home/jiangtanzju/software/anaconda3/lib/python3.7/site-packages/notebook/services/contents/filemanager.py", line 540, in delete_file
        send2trash(os_path)
      File "/home/jiangtanzju/software/anaconda3/lib/python3.7/site-packages/send2trash/plat_other.py", line 192, in send2trash
        trash_move(path_b, dest_trash, topdir)
      File "/home/jiangtanzju/software/anaconda3/lib/python3.7/site-packages/send2trash/plat_other.py", line 103, in trash_move
        os.rename(src, op.join(filespath, destname))
    OSError: [Errno 18] Invalid cross-device link: b'/data/jiangtan/untitled.txt' -> b'/home/jiangtanzju/.local/share/Trash/files/untitled 1.txt'

解决方案

.jupyter/jupyter_notebook_config.py文件中加入(会导致删除后的文件无法恢复):

c.FileContentsManager.delete_to_trash = False

保存后重新启动jupyter即可

原因

在jupyter的前端删除一个文件时,开发者希望能够把文件移动到垃圾箱里(原因见此撕逼记录),于是他们使用了send2trash这个python包来实现。但这个包的使用有众多的限制,例如要求在linux平台下被删除的文件必须和用户主目录位于同一设备上,否则就会报我上面贴的那个OSError: [Errno 18]这个error。

于是在这种情况下,后端会在用户删除文件的时候,粗略的检查一下该情况下是否能使用send2trash(源码)
img

但这种粗略的判断会遗漏掉很多情况,例如开启jupyter的用户,其主目录是位于一个docker容器内。在这种情况下,删除文件的路径和用户主目录并不在同一设备下,而这种判断方式却认为是在同一设备中,从而导致了send2trash的误用。

我推断上方的解决方案中加入的c.FileContentsManager.delete_to_trash = False就是让这里的self.delete_to_trash变成了False,从而强制不使用send2trash,强制删除文件而不是移动文件到垃圾箱,于是避免了error。

开发者同样在一个issue里指出了这一个小BUG:
在这里插入图片描述

不过看了看当时开发者提PR的comments,感觉这个BUG是不会修复了…
在这里插入图片描述
不过讲道理,我觉得这个主要是os.rename的锅,也就是send2trash这个包的问题,同样也有人提了相关issue,如jupyterlab#5781,不过尚未得到有效回复和解决。

https://blog.csdn.net/j___t/article/details/99706137